2009-09-10 30 views
16

Ho una funzione che ha la seguente firma ...Convertire un albero di espressione a stringa di codice sorgente

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

Sto cercando di trovare un modo per convertire il parametro di "espressione" di nuovo a qualcosa di simile al codice sorgente originale (o almeno una rappresentazione di # ac del codice sorgente originale). Quindi, se qualcuno chiama la funzione come questo ...

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

... Mi piacerebbe essere in grado di convertire l'espressione a questo ...

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

Qualcuno ha fatto questo?

+0

qual è il contesto di questo? –

+0

Sto sperimentando alcune idee per un framework di test unitario. La mia idea è che se si prova contro un lambda e il test fallisce, si può effettivamente mostrare il codice che ha fallito. Ad esempio, invece di ottenere "previsto: 4 effettivo: 5", potresti ricevere un messaggio più simile a "previsto: user.ge == 4 actual: user.ge == 5" – herbrandson

risposta

8

Ecco un interessante articolo, con il codice, discutendo la conversione di alberi di espressione di nuovo in qualcosa che assomiglia (approssimativamente) la fonte originale:

Expression Trees-Lambdas to CodeDom Conversion

Come un lato nota, hanno hai provato a chiamare il metodo ToString dell'espressione?

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

Ho provato a utilizzare ToString(), ma mi dà qualcosa di piuttosto brutto ... (Converti (((valore (LambdaToStringSpike.Program + <> c__DisplayClass0) .i + valore (LambdaToStringSpike.Program + <> c__DisplayClass0) .j) * 9)) = Arrotonda ((Converti (value (LambdaToStringSpike.Program + <> c__DisplayClass0) .j)/Converti ((valore (LambdaToStringSpike.Program + <> c__DisplayClass0) .i - 3))), 4)) – herbrandson

+1

Sì, penso che l'output che stai vedendo sia quello che viene generato dietro le quinte del compilatore C# per gestire le variabili catturate 'i' e' j'. Nei miei esempi, 'i' e' j' sono locali, quindi l'output è molto più vicino al codice sorgente originale. – LukeH

6

Mi sono appena imbattuto in questo; Ho scritto una libreria libera, open-source che fornisce un metodo di estensione per creare una stringa di codice sorgente come da un'espressione:

using AgileObjects.ReadableExpressions; 

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

ho scritto a blog a questo proposito, la fonte è on GitHub, c'è a NuGet package contenente un metodo di estensione e ho scritto una serie di Debugger Visualizer per VS 10 - 17 che sono in the Visual Studio Marketplace.

Problemi correlati