Analyse d’arbres d’expression lambda

J’essaie d’utiliser des expressions lambda dans un projet pour mapper une API de requête tierce. Donc, j’parsing manuellement l’arbre d’expression.

Si je passe dans une expression lambda comme:

p => p.Title == "title" 

tout fonctionne.

Cependant, si mon expression lambda ressemble à:

 p => p.Title == myaspdropdown.SelectedValue 

Avec le débogueur .NET, je ne vois pas la valeur réelle de cette fonction. Au lieu de cela, je vois quelque chose comme:

 p => p.Title = (value(ASP.usercontrols_myaspusercontrol_ascx).myaspdropdown.SelectedValue) 

Ce qui donne? Et lorsque j’essaie de saisir le côté droit de l’expression sous forme de chaîne, j’obtiens (value(ASP.usercontrols_myaspusercontrol_ascx).myaspdropdown.SelectedValue) place de la valeur réelle. Comment puis-je obtenir la valeur réelle?

N’oubliez pas que lorsque vous utilisez l’expression lambda comme un arbre d’expression, vous ne disposez pas de code exécutable. Vous avez plutôt une arborescence d’éléments d’expression qui composent l’expression que vous avez écrite.

Charlie Calvert a un bon post qui en parle en détail. Voici un exemple d’utilisation d’un visualiseur d’expressions pour le débogage d’expressions.

Dans votre cas, pour obtenir la valeur du côté droit de l’expression d’égalité, vous devez créer une nouvelle expression lambda, la comstackr, puis l’invoquer.

J’ai hacké un exemple rapide de ceci – espérons que cela répond à vos besoins.

 public class Class1 { public ssortingng Selection { get; set; } public void Sample() { Selection = "Example"; Example(p => p.Title == Selection); } public void Example(Expression> exp) { BinaryExpression equality = (BinaryExpression)exp.Body; Debug.Assert(equality.NodeType == ExpressionType.Equal); // Note that you need to know the type of the rhs of the equality var accessorExpression = Expression.Lambda>(equality.Right); Func accessor = accessorExpression.Comstack(); var value = accessor(); Debug.Assert(value == Selection); } } public class Book { public ssortingng Title { get; set; } } 

Pour obtenir la valeur réelle, vous devez appliquer la logique de l’arborescence des expressions à votre contexte.

L’intérêt des arbres d’expression est qu’ils représentent la logique sous forme de données plutôt que d’évaluer l’expression. Vous aurez besoin de comprendre ce que l’expression lambda signifie vraiment. Cela peut vouloir dire en évaluer certaines parties par rapport à des données locales – vous devrez le décider vous-même. Les arbres d’expression sont très puissants, mais l’parsing et l’utilisation ne sont pas simples. (Demandez à n’importe qui qui a écrit un fournisseur LINQ … Frans Bouma a déploré les difficultés à plusieurs resockets.)

Je viens de lutter avec exactement le même problème, merci Bevan. Sur une extension, voici un modèle générique que vous pouvez utiliser pour extraire la valeur (en l’utilisant dans mon moteur de requête).

  [TestFixture] public class TestClass { [Test] public void TEst() { var user = new User {Id = 123}; var idToSearch = user.Id; var query = Creator.CreateQuery() .Where(x => x.Id == idToSearch); } } public class Query { public Query Where(Expression> filter) { var rightValue = GenericHelper.GetVariableValue(((BinaryExpression)((UnaryExpression)filter.Body).Operand).Right.Type, ((BinaryExpression)((UnaryExpression)filter.Body).Operand).Right); Console.WriteLine(rightValue); return this; } } internal class GenericHelper { internal static object GetVariableValue(Type variableType, Expression expression) { var targetMethodInfo = typeof(InvokeGeneric).GetMethod("GetVariableValue"); var genericTargetCall = targetMethodInfo.MakeGenericMethod(variableType); return genericTargetCall.Invoke(new InvokeGeneric(), new[] { expression }); } } internal class InvokeGeneric { public T GetVariableValue(Expression expression) where T : class { var accessorExpression = Expression.Lambda>(expression); var accessor = accessorExpression.Comstack(); return accessor(); } } 

Je ne suis pas sûr de comprendre. Où voyez-vous cela? Est-ce au moment de la conception ou de l’exécution? Les expressions lambda peuvent être considérées essentiellement comme des delegates anonymes et fonctionneront avec une exécution différée. Donc, vous ne devriez pas vous attendre à voir la valeur affectée avant que l’exécution ne soit passée, évidemment.
Je ne pense pas que ce soit vraiment ce que vous voulez dire cependant … si vous clarifiez un peu la question, je peux peut-être vous aider 🙂