首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >表达式树上的ToString会产生格式错误的输出

表达式树上的ToString会产生格式错误的输出
EN

Stack Overflow用户
提问于 2014-05-03 06:55:16
回答 2查看 634关注 0票数 4

当我使用Expression.ToString()将表达式树转换为人类可读的形式时,结果如下所示:

代码语言:javascript
复制
x => ((x.ID > 2) OrElse (x.ID != 6))
x => ((x.ID > 2) AndAlso (x.ID != 6))

理想情况下,我希望输出显示操作符,而不是"OrElse“和"AndAlso":

代码语言:javascript
复制
x => ((x.ID > 2) || (x.ID != 6))
x => ((x.ID > 2) && (x.ID != 6))

作为变通办法,我可以使用string.Replace()方法。

代码语言:javascript
复制
.Replace("AndAlso", "&&")
.Replace("OrElse", "||")

但这有明显的弱点,而且看起来很尴尬。此外,我不想创建一个大的‘替换’部分或巨大的正则表达式树,只是为了获得正确的格式。

有没有一种简单的方法来获得类似于人类可读的代码形式的表达式树?

EN

回答 2

Stack Overflow用户

发布于 2014-05-03 07:49:02

不幸的是,正确做到这一点的最简单方法是编写您自己的ExpressionVisitor类,该类将生成C#格式的输出代码。

要做到这一点,最简单的方法是使用来自参考源的ExpressionStringBuilder作为起点,并调整它,直到您对输出结果满意为止。

票数 0
EN

Stack Overflow用户

发布于 2018-09-23 21:52:44

当我对表达式表示的代码的语义感兴趣时,而不是对确切的语法树感兴趣时,我发现将其编译为程序集并在ILSpy中查看非常有用。方便的方法:

代码语言:javascript
复制
// Code is probably adapted from some other answer, don't remember
public static void CompileToAssemblyFile(
  this LambdaExpression expression,
  string outputFilePath = null,
  string assemblyAndModuleName = null,
  string typeName = "TheType",
  string methodName = "TheMethod",
  // Adjust this
  string ilSpyPath = @"C:\path\to\ILSpy.exe")
{
  assemblyAndModuleName = assemblyAndModuleName ?? nameof(CompileToAssemblyFile);

  outputFilePath = outputFilePath ??
                   Path.Combine(
                     Path.GetTempPath(),
                     $"{assemblyAndModuleName}_{DateTime.Now:yyyy-MM-dd_HH_mm_ss}_{Guid.NewGuid()}.dll");

  var domain = AppDomain.CurrentDomain;
  var asmName = new AssemblyName {Name = assemblyAndModuleName};

  var asmBuilder = domain.DefineDynamicAssembly(
    asmName,
    AssemblyBuilderAccess.RunAndSave,
    Path.GetDirectoryName(outputFilePath));

  string outputFileName = Path.GetFileName(outputFilePath);

  var module = asmBuilder.DefineDynamicModule(
    assemblyAndModuleName,
    outputFileName,
    true);

  var typeBuilder = module.DefineType(typeName, TypeAttributes.Public);

  var methodBuilder = typeBuilder.DefineMethod(
    methodName,
    MethodAttributes.Public | MethodAttributes.Static,
    expression.ReturnType,
    expression.Parameters.Select(p => p.Type).ToArray());

  var pdbGenerator = DebugInfoGenerator.CreatePdbGenerator();

  expression.CompileToMethod(methodBuilder, pdbGenerator);

  typeBuilder.CreateType();

  asmBuilder.Save(outputFileName);

  Process.Start(ilSpyPath, outputFilePath);
}

(这与语法树不太相符,因为它既要经过LambdaCompiler执行的Expression -> IL转换,又要经过ILSpy进行的IL -> C#反编译。它可以通过将一些goto转换为循环,以及通过生成实际的C#来提高可读性。)

如果Expression包含“非平凡常量”(活动对象),这将会失败;但对于这一点,可以编写一个访问器,将常量替换为新变量,然后在顶层对这些变量进行lambda抽象。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23438154

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档