ICSharpCode.Decompiler + Mono.Cecil & # 8594; How to generate code for one method?

I can use Mono.Cecil and ICSharpCode.Decompiler to generate code for a type or assembly.

But if I try to generate the code for one method, I get the error "The reference to the object is not installed in the instance of the object."

Can you guys tell me about this? Thanks for the help.

Code to generate code for all types inside the 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 public methods inside the 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(); } } } } } 
+4
source share
2 answers

I had the same problem. You must set the CurrentType property for the DecompilerContext. Change your code to

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

When I recently implemented a fast C # decompiler (based on MonoDecompiler), I used 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 mini C # decompilation tool is created using the script https://github.com/o2platform/O2.Platform.Scripts/blob/master/3rdParty/MonoCecil/Utils/Tool%20-%20C%23%20Quick%20Decompiler.h2

+3
source

Source: https://habr.com/ru/post/1402731/


All Articles