ICSharpCode.Decompiler + Mono.Cecil -> How to generate code for a single method?

∥☆過路亽.° 提交于 2020-01-12 09:15:16

问题


I'm able to use Mono.Cecil and ICSharpCode.Decompiler to generate the code for a type or an assembly.

But if I try to generate the code for a single method I'll get an error "Object reference not set to an instance of an object."

Can you guys give me any hints about this? Thanks ahead for all the help.

Code to generate code for all the types inside an assembly:

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();
        }
    }
}

Code to generate code for all the public methods inside an assembly:

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();
                }
            }
        }
    }
}

回答1:


I had the same problem. You should set the property CurrentType of the DecompilerContext. Change your code to

astBuilder = new AstBuilder(new ICSharpCode.Decompiler.DecompilerContext(assemblyDefinition.MainModule) { CurrentType = typeInAssembly } );



回答2:


When I recently implemented a quick C# decompiler (MonoDecompiler based), I used the ILSpy methods :)

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);
    }
}

For this and other examples see: https://github.com/o2platform/O2.Platform.Scripts/blob/master/3rdParty/MonoCecil/CecilDecompiler/CecilDecompiler.cs

The stand-alone mini C# decompilation tool is created by this script https://github.com/o2platform/O2.Platform.Scripts/blob/master/3rdParty/MonoCecil/Utils/Tool%20-%20C%23%20Quick%20Decompiler.h2



来源:https://stackoverflow.com/questions/9811448/icsharpcode-decompiler-mono-cecil-how-to-generate-code-for-a-single-method

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!