2009-09-10 8 views
16

J'ai une fonction qui a la signature suivante ...Convertir un arbre d'expression à chaîne code source

public string DoJunk(Expression<Func<bool>> expression) 

J'essaie de trouver un moyen de convertir le paramètre « expression » à quelque chose qui ressemble à la code source original (ou au moins la représentation aC# du code source original). Donc, si quelqu'un appelle la fonction comme ça ...

DoJunk(() => (i + j) * 9 == Math.Round((double)j/(i - 3), 4)) 

... Je voudrais être en mesure de convertir l'expression à cette ...

(i + j) * 9 == Math.Round((double)j/(i - 3), 4) 

Quelqu'un at-il fait cela?

+0

Quel est le contexte? –

+0

J'expérimente avec quelques idées pour un cadre de test unitaire. Mon idée est que si vous testez contre un lambda et que le test échoue, vous pouvez réellement montrer le code qui a échoué. Par exemple, au lieu d'obtenir "attendu: 4 réel: 5", vous pourriez obtenir un message plus comme "attendu: user.Age == 4 réel: user.Age == 5" – herbrandson

Répondre

8

Voici un article intéressant, avec le code, discuter de la conversion des arbres d'expression de nouveau dans quelque chose qui ressemble à (à peu près) la source d'origine:

Expression Trees-Lambdas to CodeDom Conversion

Comme un côté note, ont vous avez essayé d'appeler la méthode ToString de l'expression?

Expression<Func<int, int, bool>> expr = 
    (i, j) => (i + j) * 9 == Math.Round((double)j/(i - 3), 4); 

Console.WriteLine(expr.ToString()); 
// (i, j) => (Convert(((i + j) * 9)) = Round((Convert(j)/Convert((i - 3))), 4)) 

Console.WriteLine(expr.Body.ToString()); 
// (Convert(((i + j) * 9)) = Round((Convert(j)/Convert((i - 3))), 4)) 
+1

J'ai essayé d'utiliser ToString(), mais cela me donne quelque chose d'assez désagréable ... (Convertir (((valeur (LambdaToStringSpike.Program + <> c__DisplayClass0) .i + valeur (LambdaToStringSpike.Program + <> c__DisplayClass0) .j) * 9)) = Ronde ((Convertir (valeur (LambdaToStringSpike.Program + <> c__DisplayClass0) .j)/Convert ((valeur (LambdaToStringSpike.Program + <> c__DisplayClass0) .i - 3))), 4)) – herbrandson

+1

Oui, je pense que la sortie que vous voyez est ce qui est généré en coulisses par le compilateur C# pour gérer les variables capturées 'i' et' j'. Dans mes exemples, 'i' et' j' sont locaux, donc la sortie est beaucoup plus proche du code source original. – LukeH

6

Je viens de passer par là; J'ai écrit une bibliothèque libre et open source, qui fournit une méthode d'extension pour créer une chaîne comme code source d'une expression:

using AgileObjects.ReadableExpressions; 

var myExpression = CreateBigExpressionTree(); 
var expressionSource = myExpression.ToReadableString(); 

J'ai écrit a blog à ce sujet, la source est on GitHub, il y a a NuGet package contenant une méthode d'extension, et j'ai écrit un ensemble de visualiseurs de débogueur pour VS 10 - 17 qui sont dans the Visual Studio Marketplace.

Questions connexes