How to create a method at runtime using Reflection.emit

You use a MethodBuilder to define methods. To define the method body, you call GetILGenerator() to get an ILGenerator, and then call the Emit methods to emit individual IL instructions. There is an example on the MSDN documentation for MethodBuilder, and you can find other examples of how to use reflection emit on the Using Reflection Emit page:

public static void AddMethodDynamically(TypeBuilder myTypeBld,
                                    string mthdName,
                                    Type[] mthdParams,
                                    Type returnType,
                                    string mthdAction)
{
    MethodBuilder myMthdBld = myTypeBld.DefineMethod(
                                            mthdName,
                                            MethodAttributes.Public |
                                            MethodAttributes.Static,
                                            returnType,
                                            mthdParams);
    ILGenerator ILout = myMthdBld.GetILGenerator();
    int numParams = mthdParams.Length;
    for (byte x = 0; x < numParams; x++)
    {
        ILout.Emit(OpCodes.Ldarg_S, x);
    }
    if (numParams > 1)
    {
        for (int y = 0; y < (numParams - 1); y++)
        {
            switch (mthdAction)
            {
                case "A": ILout.Emit(OpCodes.Add);
                    break;
                case "M": ILout.Emit(OpCodes.Mul);
                    break;
                default: ILout.Emit(OpCodes.Add);
                    break;
            }
        }
    }
    ILout.Emit(OpCodes.Ret);
}

It sounds like you’re looking for resources on writing MSIL. One important resource is the OpCodes class, which has a member for every IL instruction. The documentation describes how each instruction works. Another important resource is either Ildasm or Reflector. These will let you see the IL for compiled code, which will help you understand what IL you want to write. Running your GetDetailsMethod through Reflector and setting the language to IL yields:

.method public hidebysig instance string GetDetails() cil managed
{
    .maxstack 4
    .locals init (
        [0] string Details,
        [1] string CS$1$0000,
        [2] int32 CS$0$0001)
    L_0000: nop 
    L_0001: ldstr "Name = "
    L_0006: ldarg.0 
    L_0007: call instance string ConsoleApplication1.TestClass::get_Name()
    L_000c: ldstr ", Size = "
    L_0011: ldarg.0 
    L_0012: call instance int32 ConsoleApplication1.TestClass::get_Size()
    L_0017: stloc.2 
    L_0018: ldloca.s CS$0$0001
    L_001a: call instance string [mscorlib]System.Int32::ToString()
    L_001f: call string [mscorlib]System.String::Concat(string, string, string, string)
    L_0024: stloc.0 
    L_0025: ldloc.0 
    L_0026: stloc.1 
    L_0027: br.s L_0029
    L_0029: ldloc.1 
    L_002a: ret 
}

To generate a method like that dynamically, you will need to call ILGenerator.Emit for each instruction:

ilGen.Emit(OpCodes.Nop);
ilGen.Emit(OpCodes.Ldstr, "Name = ");
ilGen.Emit(OpCodes.Ldarg_0);
ilGen.Emit(OpCodes.Call, nameProperty.GetGetMethod());
// etc..

You may also want to look for introductions to MSIL, such as this one: Introduction to IL Assembly Language.

Leave a Comment