34

我正在解析一个表达式树。给定 ExpressionType.MemberAccess 的 NodeType,我如何获取该字段的值?

来自 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
}
4

2 回答 2

44

[为清楚起见更新]

第一的; 将其Expression转换为MemberExpression.

AMemberExpression有两件事很有趣:

  • .Member -成员的PropertyInfo/FieldInfo
  • .Expression - 为获取 .Member 的“obj”而求值的表达式

即,如果您可以将 评估.Expression为“obj”,并且.Memberis a ,那么您可以通过onFieldInfo获得实际值(并且非常相似)。.GetValue(obj)FieldInfoPropertyInfo

问题是评估.Expression非常棘手;-p

显然,如果结果是 - 你会很幸运ConstantExpression- 但​​在大多数情况下并非如此;它可以是 a ParameterExpression(在这种情况下,您需要知道要评估的实际参数值),或Expressions 的任何其他组合。

在许多情况下,一个简单的(也许是懒惰的)选项是使用.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);    
    }

}
于 2008-10-26T23:38:17.717 回答
24

非常感谢上面的 Marc Gravell。我真的很感谢他的帮助。

事实证明,就我而言。该问题可以通过以下方式解决:

object value = Expression.Lambda(expBody.Right).Compile().DynamicInvoke();

再次感谢马克!

于 2008-10-27T02:28:33.723 回答