且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何在运行时使用 Reflection.emit 创建方法

更新时间:2023-01-14 18:08:36

您使用 MethodBuilder 来定义方法.要定义方法主体,请调用 GetILGenerator() 以获取 ILGenerator,然后调用Emit 方法来发出单独的 IL 指令.MethodBuilder 的 MSDN 文档中有一个示例,您可以在 使用反射发射 页面:

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);
}

听起来您正在寻找有关编写 MSIL 的资源.一个重要的资源是 OpCodes 类,它每个 IL 指令都有一个成员.该文档描述了每条指令的工作原理.另一个重要的资源是 Ildasm反射器.这些将让您看到已编译代码的 IL,这将帮助您了解要编写的 IL.通过 Reflector 运行您的 GetDetailsMethod 并将语言设置为 IL 产生:


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 
}

要动态生成这样的方法,您需要为每条指令调用 ILGenerator.Emit:

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..

您可能还想查找 MSIL 的介绍,例如:Introduction to MSILIL 汇编语言.

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