The only thing I had some problems with were local variables or parameters.
Consider the following code:
int a = 3;
Get<Person>(p => p.Age == a);
the class Person
public class Person
{
public int Age { get; set; }
}
and the method
public static void Get<T>(Expression<Func<T, bool>> e)
{
MemberExpression member = (MemberExpression)((BinaryExpression)e.Body).Right;
ConstantExpression constant = (ConstantExpression)member.Expression;
Console.WriteLine(constant.Value.ToString());
}
when analyzing the expression tree then You see that the right expression of the BinaryExpression is of type ConstantExpression. Normally ConstantExpression contain directly a value. But this is not the case here! The console writeline produces the following: "ConsoleApplication1.Program+<>c__DisplayClass0"
The value of the constant expression is an anonymous object which is created on the fly. This object has a field which is named a and that field contains the value.
Therefore I had to do the following:
public static void Get<T>(Expression<Func<T, bool>> e)
{
MemberExpression member = (MemberExpression)((BinaryExpression)e.Body).Right;
ConstantExpression constant = (ConstantExpression)member.Expression;
FieldInfo info = (FieldInfo)member.Member;
Console.WriteLine(info.GetValue(constant.Value).ToString());
}
Instead of evaluating the expression which is associated to the MemberExpression.Expression I used the Member and casted it to a FieldInfo. Then I called the GetValue method passing it the value of the ConstantExpression which is basically the object. In this way I finally got the correct value of a.
The same works also for method parameters. Consider this code:
public static void FromMethod(int a)
{
Get<Person>(p => p.Age == a);
}
there we have exactly the same problem and it can be resolved in the way described above.