5

I'm looking for a way of parsing a conditional expression to a string.

The best example I can think of is LINQ-to-SQL. It uses ExpressionVisitors to format "Where" clauses. Example:

from a in b where a.x == 5 && a.y < 3 select a

That would translate into the following string (approximately, MSSQL is not current for me):

"SELECT * FROM b WHERE x = 5 AND y < 3"

From what I've read, this was done using the ExpressionVisitor class, as explained in this article: Link

Now the problem is that I don't use LINQ, but I need this particular functionality. Is there a way of parsing a condition like that? I'm willing to do anything with reflection, delegates, lambda, etc.

Honestly, I don't think it's possible, but my brain is a bit fried (read: be nice if the question is ridiculous), so I figured I might just as well give S/O a try.

EDIT: Final usage example:

// Usage:
foo.Bar(foo => foo.X == 5 && foo.Y < 3)

// Ideal string output (variable name (foo) is not needed):
"foo.X == 5 && foo.Y < 3"

EDIT 2: Yes, a number can be lower than 3 and equal to 5. Told you my brain is fried.

1
  • LINQ-to-SQL does exactly this. If you write your own, you’d be reimplementing LINQ-to-SQL, which already exists — that seems like a pointless effort. (Yet people have done it; google for IQToolkit for example.) You said “I don't use LINQ” but your code says the opposite (it’s full of LINQ; expression trees are considered to be part of LINQ). Commented Nov 17, 2010 at 2:15

2 Answers 2

4

If it is about about building the expression tree itself, then you could leverage C# compiler abilities.

It is legal to pass a lambda expression to a function acception an Expression>, as long as type arguments of Func are known. For example

 private static void PrintExpression(Expression<Func<int, bool>> lambda)
 {
      Console.WriteLine(lambda.ToString());
 }

can be called as

 PrintExpression(a=> a > 0 && a < 5);

You can improvise with generics as

private static void PrintExpression<T1,T2>(Expression<Func<T1, T2>> lambda)
{
      Console.WriteLine(lambda.ToString());
}

and calling it with

   PrintExpression<int, bool>(a=> a > 0 && a < 5);

For custom printing of the expression part, you can write a simple recursive function that prints an expression or any other logic that suits you.

Remember, the lambda expression is compiled into an Expression at compile time - so can't subsititute it with already compiled Func.

As an alternative to this, you can always build a custom query provider, but that would be slightly deviating from the purpose - as you'd need to bind it some sort of queryable (custom again).

Sign up to request clarification or add additional context in comments.

Comments

3

Try something like this:

static string GetExpressionString<T>(Expression<Func<T, bool>> expression)
{
    return expression.Body.ToString();
}

Usage as so:

string s = GetExpressionString<Foo>(foo => foo.X == 5 && foo.Y < 3);

Which will return:

((foo.X = 5) && (foo.Y < 3))

2 Comments

Oh wow, I swear mho's answer wasn't here when I posted mine! His is a bit more in-depth, but I'll leave mine here I guess.
I'd like to add that removing any strong typing and allowing "object" would be much more useful. :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.