ExpressionType.MemberAccess型を指定すると、フィールド値を取得するにはどうすればよいですか?
-
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();
再びマークに感謝します!