2012-03-21 20 views
4

我可以使用Mono.Cecil和ICSharpCode.Decompiler來生成類型或程序集的代碼。ICSharpCode.Decompiler + Mono.Cecil - >如何爲單個方法生成代碼?

但是,如果我嘗試生成單個方法的代碼,我會得到一個錯誤「對象引用未設置爲對象的實例。」

你們可以給我提示嗎?感謝所有的幫助。

代碼來生成代碼的組件內部的所有類型:

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

哪一行會引發異常? – svick 2012-03-21 19:26:21

+0

任何堆棧跟蹤? – sisve 2012-03-21 20:26:55

+0

你有沒有想過這個?當我打電話給AstBuilder.AddMethod時,我收到異常... – jaspernygaard 2012-08-28 21:45:13

回答

6

我有同樣的問題。您應該設置DecompilerContext的屬性CurrentType。更改您的代碼

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

當我最近實施了一個快速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

獨立迷你C#反編譯工具由此腳本創建https://github.com/o2platform/O2.Platform.Scripts/blob/master/3rdParty/MonoCecil/Utils/Tool%20-%20C%23%20Quick%20Decompiler.h2