2009-01-21 7 views
0

Voici le contexte de ma question:Est-il possible de transformer une instance de délégué en une expression Lambda?

Une technique courante consiste à déclarer le paramètre d'une méthode comme une expression Lambda plutôt que comme un délégué. C'est ainsi que la méthode peut examiner l'expression pour faire des choses intéressantes comme trouver les noms des appels de méthode dans le corps de l'instance déléguée.

Le problème est que vous perdez certaines des fonctions intelli-sens de Resharper. Si le paramètre de la méthode était déclaré en tant que délégué, Resharper aiderait lors de l'écriture de l'appel à cette méthode, en vous invitant à utiliser la syntaxe x => x comme valeur d'argument pour cette méthode.

Alors ... revenir à ma question, je voudrais faire le suivi:

MethodThatTakesDelegate(s => s.Length); 
} 

private void MethodThatTakesDelegate(Func<string, object> func) 
{ 
    //convert func into expression 
    //Expression<Func<string, object>> expr = "code I need to write" 

    MethodThatTakesExpression(expr); 
} 


private void MethodThatTakesExpression(Expression<Func<string, object>> expr) 
{ 
    //code here to determine the name of the property called against string (ie the Length) 
} 
+0

Je glissait sur [cette entrée de blog] (http://blogs.msdn.com/charlie/archive/2008/01/31/expression-tree-basics.aspx) et il semble faire juste une cession directe . Cela ne fonctionnerait-il pas pour vous? – plinth

Répondre

2

Partout où vous utilisez le terme «expression lambda», vous entendez réellement «arbre d'expression».

une expression lambda est le bit dans le code source qui est

parameters => code 

par exemple,

x => x * 2 

arbres d'expression sont des instances de la classe System.Linq.Expressions.Expression (ou plutôt, l'une des classes dérivées) qui représentent le code sous forme de données.

expressions lambda sont converties par le compilateur en soit arbres d'expression (ou plutôt, le code qui génère un arbre d'expression à l'exécution) ou instances de délégué.

Vous pouvez compiler une instance de LambdaExpression (qui est l'une des sous-classes d'Expression) dans un délégué, mais vous ne pouvez pas inverser la procédure.

En théorie, il pourrait être possible d'écrire un tel « décompilateur » basée sur l'IL retourné par MethodBase.GetMethodBody dans quelques situations, mais actuellement il y a plusieurs délégués qui ne peuvent pas être représentés par des arbres d'expression. Un arbre d'expression représente une expression plutôt qu'une instruction ou un bloc d'instructions - il n'y a donc pas de bouclage, de branchement (sauf les conditions), d'affectation, etc.Je crois que cela peut changer dans .NET 4.0, bien que je ne m'attendrais pas à une étape de décompilation de Microsoft à moins qu'il y ait une bonne raison pour cela.

0

Je ne crois pas qu'il soit possible d'obtenir ce que vous voulez ici. À partir des commentaires dans votre code, il semble que vous essayez de capturer le nom de la propriété qui a fait l'affectation dans MethodThatTakesExpression. Cela nécessite une expression lambda de l'arbre d'expression qui capture le contexte de l'accès à la propriété. Au moment où vous passez un délégué dans MethodThatTakesDelegate, ce contexte est perdu. Les délégués ne stockent qu'une adresse de méthode et aucun contexte concernant les informations de méthode. Une fois cette conversion effectuée, il n'est pas possible de le récupérer.

Un exemple de la raison pour laquelle cela n'est pas possible est qu'il peut ne pas y avoir de méthode nommée sauvegardant un délégué. Il est possible d'utiliser ReflectionEmit pour générer une méthode qui n'a aucun nom et n'existe que dans la mémoire. Il est cependant possible d'affecter ceci à un objet Func.

0

Non, ce n'est pas possible.