Étant donné le type ExpressionType.MemberAccess, comment puis-je obtenir la valeur du champ?

c# expression-trees reflection

Question

Je suis en train d'analyser un arbre d'expression. Étant donné le type de noeud ExpressionType.MemberAccess, comment puis-je obtenir la valeur de ce champ?

Depuis C # MSDN docs: MemberAccess est un nœud qui représente la lecture d'un champ ou d'une propriété.

Un extrait de code serait incroyablement, incroyablement utile. Merci d'avance!!!

Mon code ressemble à ceci:

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
}

Réponse acceptée

[mis à jour pour plus de clarté]

Premier; MemberExpression l' Expression à un MemberExpression .

Un MemberExpression a deux choses d'intérêt:

  • .Member - le PropertyInfo / FieldInfo au membre
  • .Expression - expression à évaluer pour obtenir le "obj" du .Member

C'est-à-dire que si vous pouvez évaluer .Expression comme "obj" et que le .Member est un FieldInfo , vous pouvez obtenir la valeur réelle via .GetValue(obj) sur le FieldInfo (et le PropertyInfo est très similaire).

Le problème est que l'évaluation de .Expression est très délicate ;-p

Il est évident que vous avez de la chance si cela s'avère être une ConstantExpression - mais dans la plupart des cas, ce n'est pas le cas; il peut s'agir d'une ParameterExpression (dans ce cas, vous devez connaître la valeur réelle du paramètre que vous souhaitez évaluer) ou de toute autre combinaison d' Expression .

Dans de nombreux cas, une option simple (peut-être paresseuse) consiste à utiliser .Compile() pour que le framework .NET fasse le gros du travail; vous pouvez ensuite évaluer le lambda en tant que délégué dactylographié (en transmettant tous les paramètres requis par le lambda). Ce n'est pas toujours une option, cependant.

Pour montrer à quel point c'est complexe; Considérez cet exemple trivial (où j'ai codé en dur à chaque étape, plutôt que de tester, etc.):

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

}

Réponse populaire

merci beaucoup à Marc Gravell ci-dessus. J'ai vraiment apprécié son aide.

Il se trouve, dans mon cas. le problème peut être résolu via:

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

Merci encore Mark!




Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi