34

式ツリーを解析しています。NodeType が ExpressionType.MemberAccess の場合、その 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
}
4

2 に答える 2

44

[明確にするために更新]

初め; を にキャストしExpressionますMemberExpression

AMemberExpressionには 2 つの興味深い点があります。

  • .Member -メンバーへのPropertyInfo/FieldInfo
  • .Expression - .Member の「obj」を取得するために評価する式

つまり、.Expressionを "obj" に評価でき、.Memberが であるFieldInfo場合、 を介して実際の値を取得できます.GetValue(obj)(FieldInfo非常PropertyInfoに似ています)。

問題は、 の評価.Expressionが非常に難しいことです;-p

-であることが判明した場合は明らかに幸運ですConstantExpressionが、ほとんどの場合はそうではありません。ParameterExpression(この場合、評価する実際のパラメーター値を知る必要があります)、またはその他の の組み合わせですExpression

多くの場合、単純な (おそらく怠惰な) オプションは.Compile()、.NET フレームワークに面倒な作業を行わせるために を使用することです。次に、ラムダを型指定されたデリゲートとして評価できます (ラムダが必要とするパラメーターを渡します)。ただし、これは常にオプションではありません。

これがいかに複雑かを示すために。この簡単な例を考えてみましょう (テストなどではなく、すべてのステップでハードコーディングしました):

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 に答える