Bei einem Typ ExpressionType.MemberAccess, wie bekomme ich den Feldwert?

c# expression-trees reflection

Frage

Ich analysiere einen Ausdrucksbaum. Bei einem NodeType von ExpressionType.MemberAccess, wie bekomme ich den Wert dieses Feldes?

Aus C # MSDN-Dokumenten: MemberAccess ist ein Knoten, der das Lesen aus einem Feld oder einer Eigenschaft darstellt.

Ein Code-Snippet wäre unglaublich, unglaublich hilfreich. Danke im Voraus!!!

Mein Code sieht ungefähr so ​​aus:

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
}

Akzeptierte Antwort

[zur Verdeutlichung aktualisiert]

Zuerst; MemberExpression den Expression auf einen MemberExpression .

Ein MemberExpression hat zwei Dinge von Interesse:

  • .Member - die PropertyInfo / FieldInfo für das Mitglied
  • .Expression - der auszuwertende Ausdruck, um das "obj" für die .Member zu erhalten

Wenn Sie also die .Expression auf "obj" auswerten können und die .Member eine FieldInfo , können Sie den tatsächlichen Wert über .GetValue(obj) auf der FieldInfo (und PropertyInfo ist sehr ähnlich).

Das Problem ist, dass die Auswertung der .Expression sehr schwierig ist;

Offensichtlich haben Sie Glück, wenn es sich um eine ConstantExpression - aber in den meisten Fällen nicht. Es könnte eine ParameterExpression (in diesem Fall müssen Sie den tatsächlichen Parameterwert kennen, den Sie auswerten möchten) oder eine andere Kombination von Expression s.

In vielen Fällen besteht eine einfache (vielleicht faule) Option darin, .Compile() zu verwenden, um das .NET-Framework dazu zu bringen, das Heavy Lifting .Compile() . Sie können das Lambda dann als typisierten Delegaten auswerten (indem Sie alle Parameter übergeben, die das Lambda benötigt). Dies ist jedoch nicht immer eine Option.

Um zu zeigen, wie komplex das ist; Betrachten Sie dieses triviale Beispiel (wo ich bei jedem Schritt hart codiert habe, anstatt es zu testen):

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);    
    }

}

Beliebte Antwort

Vielen Dank an Marc Gravell. Ich habe seine Hilfe sehr geschätzt.

Es stellt sich heraus, in meinem Fall. Das Problem kann gelöst werden über:

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

Danke nochmal Markus!




Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum