使用 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.AstBuilder
从 MyClass
的程序集中以编程方式构建 AST 时,这些内部 classes 不包含在 AST 中(其他一切都很好)。我什至可以在 MyClass
的 TypeDecleration
的注释中看到这些生成的 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;
显然,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.AstBuilder
从 MyClass
的程序集中以编程方式构建 AST 时,这些内部 classes 不包含在 AST 中(其他一切都很好)。我什至可以在 MyClass
的 TypeDecleration
的注释中看到这些生成的 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;