Вложенные классы лямбда-выражения отсутствуют в синтаксическом дереве с декомпилятором ICSharpCode

По-видимому, декомпилятор ICSharpCode почему-то не декомпилирует внутренние классы, созданные компилятором C# для лямбда-выражения. Рассмотрим следующий пример:

В некоторых случаях лямбда-выражение в 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;
        }
    }
}

(Может быть, не совсем так, но вы поняли идею.)

Теперь проблема в том, что когда я пытаюсь построить AST программно из сборки MyClass с помощью ICSharpCode.Decompiler.Ast.AstBuilder, эти внутренние классы не включаются в AST (все остальное в порядке). Я даже вижу эти сгенерированные классы среди аннотаций MyClass TypeDecleration: аннотация с типом Mono.Cecil.TypeDefinition правильно перечисляет эти внутренние классы в своем свойстве NestedTypes (так что они были правильно загружены из сборки, но не добавлены в синтаксическое дерево; также другие, вручную созданные внутренние классы правильно декомпилируются).

Также см. эту проблему ILSpy, которую я открыл: https://github.com/icsharpcode/ILSpy/issues/686

Я пропустил что-то очевидное здесь? Я также посмотрел на сборку из ILSpy с помощью графического интерфейса, и там рассматриваемый код правильно декомпилируется (правда, не с внутренним классом, а скорее реконструируется лямбда).


person Piedone    schedule 21.03.2016    source источник


Ответы (1)


Я обнаружил проблему: вам нужно запустить 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;
person Piedone    schedule 22.03.2016