Arbres d'expression et invocation d'un délégué

.net c# delegates expression-trees lambda

Question

J'ai donc un delegate qui pointe vers une fonction que je ne connais pas vraiment lorsque j'ai créé pour la première fois l'objet delegate . L'objet est défini sur une fonction ultérieurement.

Ensuite, je souhaite également créer un arbre d’expression qui appelle le délégué avec un argument (pour cette question, l’argument peut être 5 ). C'est le peu que je lutte avec; le code ci-dessous montre ce que je veux mais il ne compile pas.

Func<int, int> func = null;
Expression expr = Expression.Invoke(func, Expression.Constant(5));

Pour cet exemple, je pourrais le faire (c'est pratique, car je dois construire les arbres d'expression au moment de l'exécution):

Func<int, int> func = null;
Expression<Func<int>> expr = () => func(5);

Cela fait expr devenir:

() => Invoke(value(Test.Program+<>c__DisplayClass0).func, 5)

Ce qui semble vouloir dire que pour utiliser le delegate func , je dois produire la value(Test.Program+<>c__DisplayClass0).func bit.

Alors, comment puis-je créer un arbre d’expression qui appelle un délégué?

Réponse acceptée

OK, cela montre comment cela peut être fait (mais c'est très inélégant à mon avis):

Func<int, int> func = null;
Expression<Func<int, int>> bind = (x) => func(x);

Expression expr = Expression.Invoke(bind, Expression.Constant(5));

Expression<Func<int>> lambda = Expression.Lambda<Func<int>>(expr);
Func<int> compiled = lambda.Compile();

Console.WriteLine(expr);

func = x => 3 * x;
Console.WriteLine(compiled());

func = x => 7 * x;
Console.WriteLine(compiled());

Console.Read();

Essentiellement, j'utilise (x) => func(x); pour créer une fonction qui appelle ce que le délégué pointe vers. Mais vous pouvez voir que expr est trop compliqué. Pour cette raison, je ne considère pas que cette réponse est bonne, mais peut-on en tirer parti?


Réponse populaire

Je pense que ce que vous voulez faire est d'utiliser les propriétés Target et Method du délégué à transmettre pour créer une expression Call. En se basant sur l’exemple de JulianR, voici à quoi cela pourrait ressembler:

Action<int> func = i => Console.WriteLine(i * i);

var callExpr = Expression.Call(Expression.Constant(func.Target), func.Method, Expression.Constant(5));

var lambdaExpr = Expression.Lambda<Action>(callExpr);
var fn = lambdaExpr.Compile();
fn();    //  Prints 25


Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow