将表达式树转换为源代码字符串

19

我有一个函数,它的签名如下...

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

我正在尝试找到一种方法将“表达式”参数转换回类似于原始源代码(或至少是原始源代码的 c# 表示)的东西。所以,如果有人像这样调用函数...

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

我希望能够将这个表达式转换为这样...

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

有人做过这个吗?


我正在尝试一些单元测试框架的想法。我的想法是,如果您针对一个lambda函数进行测试,而测试失败,您实际上可以显示失败的代码。例如,您可以获得更像是“期望:user.Age == 4实际:user.Age == 5”这样的消息,而不是“期望:4实际:5”。 - herbrandson
你要求一个类似于C#的字符串表示,但我已经编写了一个库,可以输出其他表示形式:Visual Basic- like,需要工厂方法来创建类似表达式;对象/集合初始化语法。 - Zev Spitz
2个回答

14

我刚刚偶然发现了这个; 我写了一个免费的、开源的库,提供了一个扩展方法,可以从表达式中创建一个类似于源代码的字符串:

using AgileObjects.ReadableExpressions;

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

我已经写了一篇博客关于它,源代码在GitHub上,还有一个NuGet包 包含扩展方法,并且我已经为VS 2010 -> 2022编写了一组调试器可视化工具,这些工具在Visual Studio Marketplace上。


从Nuget的下载次数来看,这个东西比我想象中更受欢迎。 - Savo Pejović
我有一个依赖于它的映射器项目,这将增加下载次数。AutoMapper也推荐我的库来检查他们的映射执行计划! :) - Steve Wilkes
那就解释了 :) - Savo Pejović

9
这是一篇有趣的文章,涉及到代码,讨论了将表达式树转换回类似于原始源代码的东西的过程(大致上):
引用块: 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(),但它给了我一些相当难看的东西... (Convert(((value(LambdaToStringSpike.Program+<>c__DisplayClass0).i + value(LambdaToStringSpike.Program+<>c__DisplayClass0).j) * 9)) = Round((Convert(value(LambdaToStringSpike.Program+<>c__DisplayClass0).j) / Convert((value(LambdaToStringSpike.Program+<>c__DisplayClass0).i - 3))), 4)) - herbrandson
1
是的,我认为你看到的输出是由C#编译器在处理捕获变量ij时生成的幕后代码。在我的示例中,ij是本地变量,因此输出结果更接近原始源代码。 - LukeH

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接