0

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

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

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

将导致编译器添加如下内部类:

class MyClass
{
    public void MyMethod()
    ...

    public class c__DisplayClass2()
    {
        public int i;

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

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

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

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

我在这里遗漏了一些明显的东西吗?我还使用 GUI 查看了 ILSpy 的程序集,并且有问题的代码已正确反编译(尽管不是使用内部类,而是重构了 lambda)。

4

1 回答 1

0

我发现了问题:您需要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;
于 2016-03-22T14:18:22.813 回答