Passer d'un lambda à une expression est facile en utilisant un appel de méthode ...
public void GimmeExpression(Expression<Func<T>> expression)
{
((MemberExpression)expression.Body).Member.Name; // "DoStuff"
}
public void SomewhereElse()
{
GimmeExpression(() => thing.DoStuff());
}
Mais je voudrais transformer le Func en une expression, seulement dans de rares cas ...
public void ContainTheDanger(Func<T> dangerousCall)
{
try
{
dangerousCall();
}
catch (Exception e)
{
// This next line does not work...
Expression<Func<T>> DangerousExpression = dangerousCall;
var nameOfDanger =
((MemberExpression)dangerousCall.Body).Member.Name;
throw new DangerContainer(
"Danger manifested while " + nameOfDanger, e);
}
}
public void SomewhereElse()
{
ContainTheDanger(() => thing.CrossTheStreams());
}
La ligne qui ne fonctionne pas me donne l'erreur de compilation Cannot implicitly convert type 'System.Func<T>' to 'System.Linq.Expressions.Expression<System.Func<T>>'
. Un casting explicite ne résout pas la situation. Y a-t-il une possibilité de faire cela que je néglige?
at lambda_method(Closure )
pour l'invocation du délégué compilé.Réponses:
Ooh, ce n'est pas du tout facile.
Func<T>
représente un génériquedelegate
et non une expression. S'il y a un moyen de le faire (en raison des optimisations et d'autres choses effectuées par le compilateur, certaines données peuvent être jetées, il peut donc être impossible de récupérer l'expression d'origine), ce serait désassembler l'IL à la volée et inférer l'expression (ce qui n'est en aucun cas facile). Traiter les expressions lambda comme des données (Expression<Func<T>>
) est une magie faite par le compilateur (en gros, le compilateur construit un arbre d'expression dans le code au lieu de le compiler en IL).Fait connexe
C'est pourquoi les langages qui poussent les lambdas à l'extrême (comme Lisp) sont souvent plus faciles à implémenter en tant qu'interprètes . Dans ces langages, le code et les données sont essentiellement la même chose (même au moment de l'exécution ), mais notre puce ne peut pas comprendre cette forme de code, nous devons donc émuler une telle machine en construisant au-dessus un interpréteur qui la comprend (le choix fait par Lisp comme les langages) ou sacrifier la puissance (le code ne sera plus exactement égal aux données) dans une certaine mesure (le choix fait par C #). En C #, le compilateur donne l'illusion de traiter le code comme des données en permettant aux lambdas d'être interprétées comme code (
Func<T>
) et data (Expression<Func<T>>
) au moment de la compilation .la source
eval
vous devrez démarrer le compilateur, mais à part cela, il n'y a aucun problème à le faire.Expression
sur votre action de wrapper, mais il n'aurait aucune information d'arborescence d'expression sur les éléments internes dudangerousCall
délégué.la source
Func
sera caché dans une nouvelle expression. Cela ajoute simplement une couche de données sur le code; vous pouvez parcourir une couche juste pour trouver votre paramètref
sans plus de détails, vous êtes donc là où vous avez commencé.Ce que vous devriez probablement faire, c'est changer la méthode. Prenez une expression>, compilez et exécutez. En cas d'échec, vous avez déjà l'Expression à examiner.
De toute évidence, vous devez tenir compte de ses implications en termes de performances et déterminer si c'est quelque chose que vous devez vraiment faire.
la source
Vous pouvez cependant aller dans l'autre sens via la méthode .Compile () - vous ne savez pas si cela vous est utile:
la source
Si vous avez parfois besoin d'une expression et parfois besoin d'un délégué, vous avez 2 options:
Expression<...>
version, et uniquement.Compile().Invoke(...)
si vous voulez un délégué. Évidemment, cela a coûté.la source
NJection.LambdaConverter est une bibliothèque qui convertit les délégués en expression
la source
la source
call.Target
partie qui me tuait. Cela a fonctionné pendant des années, puis a soudainement cessé de fonctionner et a commencé à se plaindre d'un bla bla statique / non statique. Bref, merci!JB Evain de l'équipe Cecil Mono fait des progrès pour permettre cela
http://evain.net/blog/articles/2009/04/22/converting-delegates-to-expression-trees
la source
Changement
À
la source