How to create a method at runtime using Reflection.emit

只愿长相守 提交于 2019-11-27 19:54:53

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!