user3265328
user3265328

Reputation: 11

How to call a method on a field with ILGenerator.Emit?

I want to know how to generator the following method myMethod with ilGenerator.

public class MyClass {
     private MyField myField;

     public int myMethod(int b) {
          return myField.someMethod(b);
     }
}

Can someone help me ?

Upvotes: -1

Views: 2046

Answers (1)

Sagi
Sagi

Reputation: 9294

class Program
{
    static MethodAttributes attrs = MethodAttributes.Public | MethodAttributes.RTSpecialName | MethodAttributes.SpecialName | MethodAttributes.HideBySig;

    static Type CreateType() {
        var myDomain = Thread.GetDomain();
        var myAsmName = new AssemblyName { Name = "Demo" };
        var myAsmBuilder = myDomain.DefineDynamicAssembly(myAsmName, AssemblyBuilderAccess.RunAndSave);
        var moudle = myAsmBuilder.DefineDynamicModule("DemoModule", "Demo.dll");
        var typeBuilder = moudle.DefineType("MyClass", TypeAttributes.Public | TypeAttributes.BeforeFieldInit);
        var fieldBuilder = typeBuilder.DefineField("myField", typeof(MyField), FieldAttributes.Private);
        var ctorBuilder = typeBuilder.DefineConstructor(attrs, CallingConventions.HasThis | CallingConventions.Standard, Type.EmptyTypes);
        var methodBuilder = typeBuilder.DefineMethod("MyMethod", MethodAttributes.Public | MethodAttributes.HideBySig, typeof(int), new[] { typeof(int) });
        var ctorILGen = ctorBuilder.GetILGenerator();
        var ilGen = methodBuilder.GetILGenerator();
        var someMethod = fieldBuilder.FieldType.GetMethod("SomeMethod");

        ctorILGen.Emit(OpCodes.Ldarg_0);
        ctorILGen.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));
        ctorILGen.Emit(OpCodes.Ldarg_0);
        ctorILGen.Emit(OpCodes.Newobj, fieldBuilder.FieldType.GetConstructor(Type.EmptyTypes));
        ctorILGen.Emit(OpCodes.Stfld, fieldBuilder);
        ctorILGen.Emit(OpCodes.Ret);

        ilGen.Emit(OpCodes.Ldarg_0);
        ilGen.Emit(OpCodes.Ldfld, fieldBuilder);
        ilGen.Emit(OpCodes.Ldarg_1);
        ilGen.Emit(OpCodes.Callvirt, someMethod);
        ilGen.Emit(OpCodes.Ret);

        return typeBuilder.CreateType();
    }

    static void Main(string[] args) {
        var type = CreateType();
        dynamic instance = Activator.CreateInstance(type);

        Console.WriteLine(instance.MyMethod(10));
    }
}

will generate

public class MyClass
{
    private MyField myField;

    public MyClass() {
        myField = new MyField();
    }

    public int myMethod(int b) {
        return myField.SomeMethod(b);
    }

}
public class MyField
{
    public int SomeMethod(int i) {
        return i;
    }
}

Upvotes: 2

Related Questions