我正在解析表达式树。给定ExpressionType.MemberAccess的NodeType,如何获取该Field的值?
来自C#MSDN文档: MemberAccess是表示从字段或属性读取的节点。
代码片段令人难以置信,非常有用。在此先感谢!!!
我的代码看起来像这样:
public static List<T> Filter(Expression<Func<T, bool>> filterExp)
{
//the expression is indeed a binary expression in this case
BinaryExpression expBody = filterExp.Body as BinaryExpression;
if (expBody.Left.NodeType == ExpressionType.MemberAccess)
//do something with ((MemberExpressionexpBody.Left).Name
//right hand side is indeed member access. in fact, the value comes from //aspdroplist.selectedvalue
if (expBody.Right.NodeType == ExpressionType.MemberAccess)
{
//how do i get the value of aspdroplist.selected value?? note: it's non-static
}
//return a list
}
答案 0 :(得分:39)
[为清晰起见而更新]
首先;将Expression
投射到MemberExpression
。
MemberExpression
有两件值得关注的事情:
PropertyInfo
/ FieldInfo
即。如果您可以评估.Expression
到“obj”,并且.Member
是FieldInfo
,那么您可以通过.GetValue(obj)
上的FieldInfo
获取实际值(和PropertyInfo
非常相似)。
问题在于评估.Expression
非常棘手; -p
显然,如果事实证明是ConstantExpression
,你会很幸运 - 但在大多数情况下并非如此;它可以是ParameterExpression
(在这种情况下,您需要知道要评估的实际参数值),或Expression
s的任何其他组合。
在许多情况下,一个简单的(可能是懒惰的)选项是使用.Compile()
来使.NET框架完成繁重的任务;然后,您可以将lambda计算为类型委托(传入lambda要求的任何参数)。但是,这并不总是一种选择。
表明这是多么复杂;考虑这个简单的例子(我在每一步都进行了硬编码,而不是测试等):
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);
}
}
答案 1 :(得分:22)
非常感谢Marc Gravell。我非常感谢他的帮助。
事实证明,就我而言。问题可以通过以下方式解决:
object value = Expression.Lambda(expBody.Right).Compile().DynamicInvoke();
再次感谢马克!