Brandon Woolworth
Brandon Woolworth

Reputation: 51

Add Static Instance Field to Class and Set To Self in Constructor

Using Mono.Cecil I'm trying to patch a class to add a static field "Instance" and set it inside the constructor. It's essentially the equivalent of adding the following:

public static Class1 Instance;
public Class1() {
    // does normal constructor stuff
    Class1.Instance = this;
}

I don't know where the reference exists, though, and after looking through the OpCodes I couldn't find how I could push the reference onto the stack to store the field (OpCodes.Stfld) into my field definition.

Here's what I have so far, though.

public static void Patch(AssemblyDefinition assembly) {
    TypeDefinition wfcDefinition = assembly.MainModule.Types.First(t => t.Name == "WinFormConnection");
    MethodDefinition wfcConstructor = wfcDefinition.GetConstructors().First(t => t.IsConstructor);

    FieldDefinition instField = new FieldDefinition("Instance", FieldAttributes.Public | FieldAttributes.Static, wfcConstructor.DeclaringType);
    wfcDefinition.Fields.Add(instField);

    ILProcessor proc = wfcConstructor.Body.GetILProcessor();

    // Where does the instance exist within the stack?
    // Instruction pushInstance = proc.Create(OpCodes.?);
    Instruction allocInstance = proc.Create(OpCodes.Stfld, instField);

    // proc.Body.Instructions.Add(pushInstance);
    proc.Body.Instructions.Add(allocInstance);
}

Upvotes: 1

Views: 202

Answers (1)

Vagaus
Vagaus

Reputation: 4215

this is always the first argument of the method, i.e, you need to do something like:

...
  Instruction pushInstance = proc.Create(OpCodes.Ldarg_0);
  proc.Body.Instructions.Add(pushInstance);

  Instruction store = proc.Create(OpCodes.Stsfld, instField);
  proc.Body.Instructions.Add(store);

also notice that you need to use Stsfld (store static field) instead of Stfld (store instance field)

Upvotes: 1

Related Questions