How to add code into method?

Topics: Metadata Model, PE reader, PE Writer, Source Model
Apr 30, 2011 at 5:34 PM

Hi guys!

I'm trying insert an source code into method body. I do it like so: 


IMetadataHost host = new PeReader.DefaultHost();
IModule module = host.LoadUnitFrom("ModelAssembly.dll") as IModule;
IMethodDefinition method = /*I select necessary method here*/ 
ILGenerator ilGenerator = new ILGenerator(host, method);
ilGenerator.Emit(OperationCode.Ldstr, "hello");               
ilGenerator.Emit(OperationCode.Call, "System.Void System.Console.WriteLine(System.String)");               

Stream peStream = File.Create("ModelAssembly_new.dll");
PeWriter.WritePeToStream(module, host, peStream);           

I expect to see new lines of code into top of body. But, when i open ModelAssembly_new.dll into IL DASM, i see old version of method body. Thus, source code didn't add to assembly. How i do it correctly? I hope, anyone will show correct example here. Thank for help!


Apr 30, 2011 at 6:01 PM

The object model that you get from LoadUnitFrom is immutable. The ILGenerator instance is not going to change that object model, it will merely generate a new il stream. The ILMutator sample application shows how you can go about making a mutable copy of the object model and changing the il.

Depending on your application, you may find it easier to use the Code Model from the companion project (

May 1, 2011 at 8:48 PM
Edited May 1, 2011 at 8:48 PM

Thank you vary match! I find solution and i give it below. I hope, it will help someone. Following source code have been written on the basis of ILMutator simple application.  

IMetadataHost host = new PeReader.DefaultHost();
IModule module = host.LoadUnitFrom("ModelAssembly.dll") as IModule; // Load original module

module = new MetadataDeepCopier(host).Copy(module); // Make a editable copy
ILMutator mutator = new ILMutator(host); // Create class, which will add some source code in any method
module = mutator.Visit(module); // Create new modified assembly

Stream s = File.Create(outputPath);           
PeWriter.WritePeToStream(module, host, s);           

public class ILMutator : MutatingVisitor    
        public ILMutator(IMetadataHost host) 
            : base(host, false) { }

        public override MethodBody Mutate(MethodBody methodBody)       
            // Create Console.WriteLise(String) method reference
            Microsoft.Cci.NamespaceTypeReference SystemDotConsoleType =
              new Microsoft.Cci.NamespaceTypeReference(host,
                0, false, false, PrimitiveTypeCode.NotPrimitive);

            IMethodReference consoleDotWriteLine = new Microsoft.Cci.MethodReference(
              host, SystemDotConsoleType, CallingConvention.Default,
              host.PlatformType.SystemVoid, host.NameTable.GetNameFor("WriteLine"),
              0, host.PlatformType.SystemString);

            // Create IL Generator
            ILGenerator generator = new ILGenerator(, methodBody.MethodDefinition);

            // Generate output into console the name of current method
            generator.Emit(OperationCode.Ldstr, methodBody.MethodDefinition.Name.Value);           
            generator.Emit(OperationCode.Call, consoleDotWriteLine);

            // Apply changes to new body
            methodBody.Operations.InsertRange(0, new List<IOperation>(generator.GetOperations()));
            methodBody.OperationExceptionInformation.AddRange(new List<IOperationExceptionInformation>(generator.GetOperationExceptionInformation()));
            return methodBody;