3

I have the following method:

public void DoSomething()
{
  Console.WriteLine("");
}

I want to modify this code with Mono Cecil. I want to create an instance of a custom class within the method:

public void DoSomething()
{
  MyClass instance = new MyClass();
  Console.WriteLine("");
}

Currently I use the following code:

  var constructorInfo = typeof(MyClass).GetConstructor(new Type[] { });
  MethodReference myClassConstructor = targetAssembly.MainModule.Import(constructorInfo);

  var processor = targetMethod.Body.GetILProcessor();
  var firstInstruction = targetMethod.Body.Instructions[1];

  var instructions = new List<Instruction>() {
      processor.Create(OpCodes.Newobj, myClassConstructor),
      processor.Create(OpCodes.Stloc_0)
  };

  foreach (var instruction in instructions)
  {
      processor.InsertBefore(firstInstruction, instruction);
  }

After applying those changes, the program is invalid and cannot be executed. If i use 'IL DASM' to look at the generated code the following statement is missing:

.locals init ([0] class [MyAssembly]MyNamespace.MyClass instance)

The rest of the IL is the same, as if I directly compile the full code. Any ideas what I am doing wrong?

Daniel
  • 920
  • 7
  • 19

1 Answers1

6

I have not tried it but by looking at the Cecil Source Code you should first create the local variable which is part of your MethodBody.

MethodBody has a Variables collection which can be filled via

body.Variables.Add( new VariableDefinition(typedef) )

Then you need to call processor.Create(xxx,indexto local variable);

That should do the trick. The only thing I did not see yet how you can get a TypeDefinition out from a Type. I think you need to load the assembly into Mono Cecil first before you can use this approach.

svick
  • 236,525
  • 50
  • 385
  • 514
Alois Kraus
  • 13,229
  • 1
  • 38
  • 64
  • Thanks for your help. I managed to add the variable. Put I still have problems to initialize it with a call to the corresponding constructor. – Daniel Aug 28 '11 at 14:03