2009-09-10 11 views
16

que tiene una función que tiene la siguiente firma ...Convertir un árbol de expresión de cadena de código fuente

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

estoy tratando de encontrar una manera de convertir el parámetro de "expresión" volver a algo parecido a la código fuente original (o al menos representación de aC# del código fuente original). Por lo tanto, si alguien llama a la función como esta ...

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

... Me gustaría ser capaz de convertir la expresión a este ...

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

Alguien ha hecho esto?

+0

¿Cuál es el contexto de esto? –

+0

Estoy experimentando con algunas ideas para un marco de prueba de unidad. Mi idea es que si prueba contra un lambda y la prueba falla, podría mostrar el código que falló. Por ejemplo, en lugar de obtener "esperado: 4 real: 5", podría obtener un mensaje más parecido a "esperado: usuario.Edad == 4 real: usuario.Edad == 5" – herbrandson

Respuesta

8

He aquí un interesante artículo, con el código, discutiendo la conversión de los árboles de expresión de nuevo en algo que se asemeja (más o menos) la fuente original:

Expression Trees-Lambdas to CodeDom Conversion

Como nota lateral, tiene ¿Intentó llamar al método ToString de la expresión?

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

He intentado usar ToString(), pero me da algo bastante desagradable mirando ... (Convertir (((valor (LambdaToStringSpike.Program + <> c__DisplayClass0) .i + valor (LambdaToStringSpike.Program + <> c__DisplayClass0) .j) * 9)) = Redondear ((Convertir (value (LambdaToStringSpike.Program + <> c__DisplayClass0) .j)/Convert ((value (LambdaToStringSpike.Program + <> c__DisplayClass0) .i - 3))), 4)) – herbrandson

+1

Sí, creo que el resultado que está viendo es el generado detrás de las escenas por el compilador C# para manejar las variables capturadas 'i' y' j'. En mis ejemplos, 'i' y' j' son locales, por lo que la salida está mucho más cerca del código fuente original. – LukeH

6

Acabo de pasar por esto; He escrito una biblioteca libre, de código abierto que proporciona un método de extensión para crear una cadena de código fuente similar a partir de una expresión:

using AgileObjects.ReadableExpressions; 

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

He escrito a blog de ello, la fuente es on GitHub, hay a NuGet package que contiene un método de extensión, y he escrito un conjunto de visualizadores de depuración para VS 10 - 17 que están en the Visual Studio Marketplace.

Cuestiones relacionadas