2009-09-10 3 views
16

У меня есть функция, которая имеет следующую сигнатуру ...Преобразование дерева выражений в строку исходного кода

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

Я пытаюсь найти способ, чтобы преобразовать параметр «выражение» назад к чему-то, приведённым исходный исходный код (или, по крайней мере, aC# представление исходного кода суса). Так что, если кто-то вызывает функцию, как это ...

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

... Я хотел бы иметь возможность преобразовать выражение этого ...

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

Кто сделал это?

+0

Каков контекст этого? –

+0

Я экспериментирую с некоторыми идеями для модульной системы тестирования. Моя идея заключается в том, что если вы протестируете против лямбда и тест не пройдет, вы можете фактически показать код, который не прошел. Например, вместо того, чтобы «ожидать: 4 фактических: 5», вы могли бы получить сообщение больше похоже на «expected: user.Age == 4 actual: user.Age == 5» – herbrandson

ответ

8

Вот интересная статья, с кодом, обсуждая преобразование деревьев выражений обратно во что-то, что напоминает (примерно) Первоисточник:

Expression Trees-Lambdas to CodeDom Conversion

В качестве побочного сведению, есть вы пытались вызвать метод выражения ToString?

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

Я попытался использовать ToString(), но это дает мне что-то довольно неприятное ... (Преобразование (((значение (LambdaToStringSpike.Program + <> c__DisplayClass0) .i + значение (LambdaToStringSpike.Program + <> c__DisplayClass0) .j) * 9)) = Round ((Преобразование (значение (LambdaToStringSpike.Program + <> c__DisplayClass0) .j)/Convert ((значение (LambdaToStringSpike.Program + <> c__DisplayClass0) .i - 3))), 4)) – herbrandson

+1

Да, я думаю, что результат, который вы видите, - это то, что создано за кулисами компилятором C# для обработки захваченных переменных 'i' и' j'. В моих примерах 'i' и' j' являются локальными, поэтому выход намного ближе к исходному исходному коду. – LukeH

6

Я только что пережил это; Я написал библиотеку бесплатно, с открытым исходным кодом, который обеспечивает метод расширения для создания исходного кода, как строка из выражения:

using AgileObjects.ReadableExpressions; 

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

я написал a blog об этом, источник on GitHub, есть a NuGet package, содержащий метод расширения, и я написал набор иллюстраторов отладчика для VS 10 - 17, которые находятся в the Visual Studio Marketplace.

Смежные вопросы