27 votes

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

J'analyse un arbre d'expression. Étant donné un NodeType d'ExpressionType.MemberAccess, comment puis-je obtenir la valeur de ce champ?

Dans les documents C # MSDN: 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
}
 

34voto

Marc Gravell Points 482669

[mise à jour pour plus de clarté]

D'abord; cast le Expression d'un MemberExpression.

Un MemberExpression a deux choses intéressantes:

  • .Membre de l' PropertyInfo / FieldInfo pour le membre
  • .L'Expression - l'expression à évaluer pour obtenir le "obj" pour le .Membre

c'est à dire si vous pouvez évaluer l' .Expression de "obj", et l' .Member est FieldInfo, alors vous pouvez obtenir la valeur réelle via .GetValue(obj) sur le FieldInfo (et PropertyInfo est très similaire).

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

Évidemment, vous avez de la chance si elle s'avère être un ConstantExpression - , mais dans la plupart des cas, il n'est pas, ça pourrait être une ParameterExpression (dans ce cas, vous aurez besoin de connaître la valeur du paramètre que vous souhaitez évaluer), ou toute autre combinaison de Expressions.

Dans de nombreux cas, un simple (peut-être paresseux) option est l'utilisation d' .Compile() pour obtenir le .NET framework pour faire le gros du travail; vous pouvez ensuite évaluer le lambda comme tapé délégué (passage de tous les paramètres que le lambda oblige). Ce n'est pas toujours une option, cependant.

Pour montrer la complexité de ce qui est; 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);    
    }

}

20voto

Keith Fitzgerald Points 2274

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

Il s'avère, dans mon cas. le problème peut être résolu via:

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

Merci encore Mark!

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X