I am parsing an Expression Tree. Given a NodeType of ExpressionType.MemberAccess, how do I get the value of that Field?
From C# MSDN docs: MemberAccess is A node that
[updated for clarity]
First; cast the Expression
to a MemberExpression
.
A MemberExpression
has two things of interest:
PropertyInfo
/ FieldInfo
to the memberi.e. if you can evaluate the .Expression
to "obj", and the .Member
is a FieldInfo
, then you can get the actual value via .GetValue(obj)
on the FieldInfo
(and PropertyInfo
is very similar).
The problem is that evaluating the .Expression
is very tricky ;-p
Obviously you get lucky if it turns out to be a ConstantExpression
- but in most cases it isn't; it could be a ParameterExpression
(in which case you'll need to know the actual parameter value that you want to evaluate), or any other combination of Expression
s.
In many cases, a simple (perhaps lazy) option is to use .Compile()
to get the .NET framework to do the heavy lifting; you can then evaluate the lambda as a typed delegate (passing in any parameters that the lambda requires). This isn't always an option, however.
To show how complex this is; consider this trivial example (where I've hard-coded at every step, rather than testing etc):
using System;
using System.Linq.Expressions;
using System.Reflection;
class Foo
{
public string Bar { get; set; }
}
static class Program
{
static void Main()
{
Foo foo = new Foo {Bar = "abc"};
Expression<Func<string>> func = () => foo.Bar;
MemberExpression outerMember = (MemberExpression)func.Body;
PropertyInfo outerProp = (PropertyInfo) outerMember.Member;
MemberExpression innerMember = (MemberExpression)outerMember.Expression;
FieldInfo innerField = (FieldInfo)innerMember.Member;
ConstantExpression ce = (ConstantExpression) innerMember.Expression;
object innerObj = ce.Value;
object outerObj = innerField.GetValue(innerObj);
string value = (string) outerProp.GetValue(outerObj, null);
}
}
thank you so so much to Marc Gravell above. I really appreciated his help.
It turns out, in my case. the problem can be solved via:
object value = Expression.Lambda(expBody.Right).Compile().DynamicInvoke();
Thanks again Mark!