I created an ExpressionVisitor implementation that overrides VisitConstant. However, when I create an expression that utilizes a local variable I can't seem to get the actual value of the variable.
public class Person
{
public string FirstName { get; set; }
}
string name = "Michael";
Expression<Func<Person, object>> exp = p => p.FirstName == name;
How in the world do I get the value of the variable "name" from the ConstantExpression? The only thing that I can think of is this:
string fieldValue = value.GetType().GetFields().First().GetValue(value).ToString();
Obviously this doesn't lend itself to being very flexible though....
A slightly more complicated example would be the following:
Person localPerson = new Person { FirstName = "Michael" };
Expression<Func<Person, object>> exp = p => p.FirstName == localPerson.FirstName;
Here's how I solved it for both cases you listed.
Basically assuming that the right hand side of your '==' can be treated like a function that takes no arguments and returns a value, it can be compiled to a C# delegate and invoked to retrieve this value without worrying about exactly what the code on the right hand side does.
So the basic example code is below
class Visitor : ExpressionVisitor {
protected override Expression VisitBinary( BinaryExpression node ) {
var memberLeft = node.Left as MemberExpression;
if ( memberLeft != null && memberLeft.Expression is ParameterExpression ) {
var f = Expression.Lambda( node.Right ).Compile();
var value = f.DynamicInvoke();
}
return base.VisitBinary( node );
}
}
It looks for a binary op looking for "arg.member == something" then just compiles/evaluates the right hand side, and for both examples your provide the result is a string "Michael".
Note, this fails if your right hand side involved using the lamda argument like
p.FirstName == CallSomeFunc( p.FirstName )