使用 ICSharpCode 反编译器的语法树中缺少 Lambda 表达式的嵌套 类

Lambda expression's nested classes missing from syntax tree with ICSharpCode Decompiler

显然,ICSharpCode 反编译器不会反编译由 C# 编译器为 lambda 表达式创建的内部 classes。考虑以下示例:

在某些情况下,C# 中的 lambda 表达式将被编译成一个内部 class,其方法包含 lambda 的主体。例如。像这样的 C# 代码:

class MyClass
{
    public void MyMethod()
    {
        Parallel.For(0, 10, i =>
        {
            ... = 3 * i;
        })
    }
}

将导致编译器添加一个内部 class,如下所示:

class MyClass
{
    public void MyMethod()
    ...

    public class c__DisplayClass2()
    {
        public int i;

        public void b__0()
        {
            ... = 3 * i;
        }
    }
}

(也许不完全是这样,但你明白了。)

现在的问题是,当我尝试使用 ICSharpCode.Decompiler.Ast.AstBuilderMyClass 的程序集中以编程方式构建 AST 时,这些内部 classes 不包含在 AST 中(其他一切都很好)。我什至可以在 MyClassTypeDecleration 的注释中看到这些生成的 classes:类型为 Mono.Cecil.TypeDefinition 的注释正确地列出了这些内部 classes它的 NestedTypes 属性(因此它们已从程序集中正确加载但未添加到语法树中;另外,其他手动创建的内部 classes 已正确反编译)。

另请参阅我打开的这个 ILSpy 问题:https://github.com/icsharpcode/ILSpy/issues/686

我是不是遗漏了什么明显的东西?我还使用 GUI 查看了来自 ILSpy 的程序集,并且有问题的代码被正确反编译了(虽然没有使用内部 class 而是重构了 lambda)。

我发现了问题:在使用语法树之前,您需要 运行 astBuilder.RunTransformations();,这也会重新创建委托。

在我这样做之前:

var assembly = AssemblyDefinition.ReadAssembly(typeof(Program).Assembly.Location);
var decompilerContext = new DecompilerContext(assembly.MainModule);
var astBuilder = new AstBuilder(decompilerContext);
astBuilder.AddAssembly(assembly);

var syntaxTree = astBuilder.SyntaxTree;

然而,要正确初始化语法树,您需要这样做:

var assembly = AssemblyDefinition.ReadAssembly(typeof(Program).Assembly.Location);
var decompilerContext = new DecompilerContext(assembly.MainModule);
var astBuilder = new AstBuilder(decompilerContext);
astBuilder.AddAssembly(assembly);
astBuilder.RunTransformations(); // This is new.

var syntaxTree = astBuilder.SyntaxTree;