Obtenir l'objet de MemberExpression?

c# expression-trees lambda

Question

Alors, disons que j'ai l'expression suivante en C #:

Expression<Func<string>> expr = () => foo.Bar;

Comment puis-je extraire une référence à foo?

Réponse acceptée

Expression<Func<string>> expr = () => foo.Bar;
var me = (MemberExpression)((MemberExpression)expr.Body).Expression;
var ce = (ConstantExpression)me.Expression;
var fieldInfo = ce.Value.GetType().GetField(me.Member.Name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
var value = (Foo)fieldInfo.GetValue(ce.Value);

Réponse populaire

J'ai eu le même problème, mais un peu plus complexe, et la réponse de Darin Dimitrov m'a donné un bon départ. Je posterai mes résultats ici, malgré le fait qu'il s'agisse d'une "vieille" question.


Cas 1: l'objet racine est un membre d'objet

    this.textBox.Text    // where 'this' has type 'Form'

... est équivalent à l'arbre d'expression suivant:

    this.textBox.Text    // where 'this' has type 'Form'

Le seul endroit dans cet arbre d'expression où vous obtenez réellement une référence d'objet provient de ConstantExpression : il vous permet d'obtenir une référence à this . L'idée de base pour obtenir une référence d'objet dans cet arbre est donc la suivante:

  1. Descendez dans l'arbre d'expression le long des axes .Expression jusqu'à atteindre un nœud ConstantExpression .

  2. .Value propriété .Value ce nœud. Ceci est la référence d'objet racine (ie. this dans l'exemple ci - dessus).

  3. À l'aide de la réflexion et des nœuds MemberInfo de l'arborescence des expressions, obtenez des références aux objets et remontez dans l'arborescence des expressions.

Voici un code qui montre ceci:

    this.textBox.Text    // where 'this' has type 'Form'

Cas 2: l'objet racine est un membre de la classe statique

    this.textBox.Text    // where 'this' has type 'Form'

... donne un arbre d'expression différent. Note à la référence null en bas à gauche:

    this.textBox.Text    // where 'this' has type 'Form'

Ici, vous ne pouvez pas arrêter la phase de "descente" en attendant une ConstantExpression . Au lieu de cela, vous arrêtez de descendre lorsque vous atteignez une référence null. Ensuite, vous récupérez la référence de l'objet racine comme suit:

    this.textBox.Text    // where 'this' has type 'Form'

La phase "ascendante" à partir de là est la même que précédemment.


Il y a certainement plus de cas (tels que les paramètres nommés en tant qu'objet racine), mais j'espère qu'à présent, j'ai compris l'idée de base, alors je vais couper ici.




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