Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting Values from ExpressionTrees

let there be:

Expression<Func<Customer, bool>> expression = c => c.Name == "John";

now i get the value by using :

string myvalue = ((ConstantExpression) bin.Right).Value;

now let there be:

string x = "John";
Expression<Func<Customer, bool>> expression = c => c.Name == x;

now i understand that

string myvalue = ((ConstantExpression) bin.Right).Value;

would generate an error because the bin.right here is not constantexpression its a field expression but the question is how do i get the value(John) out of this ?

like image 254
Stacker Avatar asked Aug 11 '10 10:08

Stacker


People also ask

How do you evaluate expression tree?

While evaluating the expression tree we replace the value at a node with any operation OP by evaluating LEFTCHILD (OP) RIGHTCHILD Here, the expression will be evaluated as 20 - 10 = 10 (FOR '-'), then '-' will be replaced by 10 (symbolic), then we evaluate for node'+', 10 + 10 = 20.

How do you evaluate an expression tree in C++?

We can evaluate an expression tree by applying the operator at the root to values obtained by recursively evaluating left and right subtrees. This can be easily done by traversing the expression tree using postorder traversal. The algorithm can be implemented as follows in C++, Java, and Python: C++


1 Answers

You could wrap the expression in a lambda and then compile and evaluate it. That would give you the value no matter what kind of expression it is.

string myvalue = Expression.Lambda<Func<string>>(bin.Right).Compile().Invoke();

Note that this won't work if the parameter c is used on the right hand side of the expression, since it wouldn't be defined. Also note that this will give you the current value of the right hand side when you call Invoke, and subsequent calls could return different values if the field in the object changes.


Update: If you don't know the type of the right hand side at compile time, you can use object, but this will break for value types like int. You will need to use Expression.Convert to force value types to be boxed before returning them. This will work for both value types and reference types:

object myvalue = Expression.Lambda<Func<object>>(
    Expression.Convert(bin.Right, typeof(object))).Compile().Invoke();

You could also use an untyped lambda and DynamicInvoke:

object myvalue = Expression.Lambda(bin.Right).Compile().DynamicInvoke();
like image 123
Quartermeister Avatar answered Sep 24 '22 16:09

Quartermeister