ExpressionType.MemberAccess型を指定すると、フィールド値を取得するにはどうすればよいですか?

StackOverflow https://stackoverflow.com/questions/238765

  •  04-07-2019
  •  | 
  •  

質問

式ツリーを解析しています。 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
}
役に立ちましたか?

解決

[わかりやすくするために更新]

最初; Expression MemberExpression にキャストします。

MemberExpression には2つの興味深いことがあります:

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

i.e。 .Expression を&quot; obj&quot;に評価でき、 .Member FieldInfo である場合、実際の値を取得するには FieldInfo .GetValue(obj)(および PropertyInfo は非常に似ています)。

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

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

多くの場合、単純な(おそらく怠zyな)オプションは、 .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);    
    }

}

他のヒント

上記のマーク・グラヴェルに感謝します。彼の助けに本当に感謝しています。

私の場合、判明しました。問題は次の方法で解決できます。

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

再びマークに感謝します!

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top