ICSharpCode.Decompiler + Mono.Cecil -> Как создать код для одного метода? - PullRequest
4 голосов
/ 21 марта 2012

Я могу использовать Mono.Cecil и ICSharpCode.Decompiler для генерации кода для типа или сборки.

Но если я попытаюсь сгенерировать код для одного метода, я получуошибка "Ссылка на объект не установлена ​​для экземпляра объекта."

Можете ли вы, ребята, дать мне какие-либо советы по этому поводу?Заранее благодарим за всю помощь.

Код для генерации кода для всех типов в сборке:

DirectoryInfo di = new DirectoryInfo(appPath);
FileInfo[] allAssemblies = di.GetFiles("*.dll");
foreach (var assemblyFile in allAssemblies)
{
    string pathToAssembly = assemblyFile.FullName;
    System.Reflection.Assembly assembly = System.Reflection.Assembly.ReflectionOnlyLoadFrom(pathToAssembly);
    Mono.Cecil.AssemblyDefinition assemblyDefinition = Mono.Cecil.AssemblyDefinition.ReadAssembly(pathToAssembly,parameters);
    AstBuilder astBuilder = null;

    foreach (var typeInAssembly in assemblyDefinition.MainModule.Types)
    {
        if (typeInAssembly.IsPublic)
        {
             Console.WriteLine("T:{0}", typeInAssembly.Name);
            //just reset the builder to include only code for a single type
            astBuilder = new AstBuilder(new ICSharpCode.Decompiler.DecompilerContext(assemblyDefinition.MainModule));
            astBuilder.AddType(typeInAssembly);
            StringWriter output = new StringWriter();
            astBuilder.GenerateCode(new PlainTextOutput(output));
            string result = output.ToString();
            output.Dispose();
        }
    }
}

Код для генерации кода для всех открытых методов внутри сборки:

DirectoryInfo di = new DirectoryInfo(appPath);
FileInfo[] allAssemblies = di.GetFiles("*.dll");
foreach (var assemblyFile in allAssemblies)
{
    string pathToAssembly = assemblyFile.FullName;
    System.Reflection.Assembly assembly = System.Reflection.Assembly.ReflectionOnlyLoadFrom(pathToAssembly);
    Mono.Cecil.AssemblyDefinition assemblyDefinition = Mono.Cecil.AssemblyDefinition.ReadAssembly(pathToAssembly,parameters);
    AstBuilder astBuilder = null;

    foreach (var typeInAssembly in assemblyDefinition.MainModule.Types)
    {
        if (typeInAssembly.IsPublic)
        {
            Console.WriteLine("T:{0}", typeInAssembly.Name);
            foreach (var method in typeInAssembly.Methods)
            {
                //just reset the builder to include only code for a single method
                astBuilder = new AstBuilder(new ICSharpCode.Decompiler.DecompilerContext(assemblyDefinition.MainModule));
                astBuilder.AddMethod(method);
                if (method.IsPublic && !method.IsGetter && !method.IsSetter && !method.IsConstructor)
                {
                    Console.WriteLine("M:{0}", method.Name);
                    StringWriter output = new StringWriter();
                    astBuilder.GenerateCode(new PlainTextOutput(output));
                    string result = output.ToString();
                    output.Dispose();
                }
            }
        }
    }
}

Ответы [ 2 ]

6 голосов
/ 22 ноября 2012

У меня была такая же проблема.Вам следует установить свойство CurrentType для DecompilerContext.Измените свой код на

astBuilder = new AstBuilder(new ICSharpCode.Decompiler.DecompilerContext(assemblyDefinition.MainModule) { CurrentType = typeInAssembly } );
3 голосов
/ 19 декабря 2012

Когда я недавно реализовал быстрый декомпилятор C # (на основе MonoDecompiler), я использовал методы ILSpy:)

public string getSourceCode(MethodDefinition methodDefinition)
{
    try
    {
        var csharpLanguage = new CSharpLanguage();
        var textOutput = new PlainTextOutput();
        var decompilationOptions = new DecompilationOptions();
        decompilationOptions.FullDecompilation = true;
        csharpLanguage.DecompileMethod(methodDefinition, textOutput, decompilationOptions);
        return textOutput.ToString();              

    }
    catch (Exception exception)
    {
        PublicDI.log.error("in getSourceCode: {0}", new object[] { exception.Message });
        return ("Error in creating source code from IL: " + exception.Message);
    }
}

Для этого и других примеров см .: https://github.com/o2platform/O2.Platform.Scripts/blob/master/3rdParty/MonoCecil/CecilDecompiler/CecilDecompiler.cs

СтендЭтот сценарий создает отдельный инструмент для декомпиляции mini C # https://github.com/o2platform/O2.Platform.Scripts/blob/master/3rdParty/MonoCecil/Utils/Tool%20-%20C%23%20Quick%20Decompiler.h2

...