繁体   English   中英

将类方法转换为IL并在运行时执行

[英]Convert class method into IL and execute it at runtime

我想将方法​​从类转换为IL代码,然后通过调用它来执行它。 我下面的示例来自msdn: https ://msdn.microsoft.com/zh-cn/library/system.reflection.emit.methodbuilder.createmethodbody( v= vs.110).aspx。

它确切地显示了我所需要的,我的问题是从类方法生成ILcode。

所以基本上我需要填写以下内容

byte[] ILcodes = new byte[] {
      0x02,   /* 02h is the opcode for ldarg.0 */
  0x03,   /* 03h is the opcode for ldarg.1 */
  0x58,   /* 58h is the opcode for add     */
  0x2A    /* 2Ah is the opcode for ret     */
};

来自类中定义的方法,例如:

public class MethodBodyDemo
{ 
    public int Add(int x, int y)
    {
        return x + y;
    }
}

我尝试了以下调用来填充字节数组:

var ILcodes = typeof(MethodBodyDemo).GetMethod("Add").GetMethodBody().GetILAsByteArray();

以下是我正在创建的示例,但它给出了一个例外:“公共语言运行时检测到无效程序。”

 public class MethodBodyDemo
{ 
    public int Add(int x, int y)
    {
        return x + y;
    }

    // This class will demonstrate how to create a method body using 
    // the MethodBuilder.CreateMethodBody(byte[], int) method.

    public static Type BuildDynType()
    {

        Type addType = null;

        AppDomain currentDom = Thread.GetDomain();

        AssemblyName myAsmName = new AssemblyName();
        myAsmName.Name = "MyDynamicAssembly";

        AssemblyBuilder myAsmBldr = currentDom.DefineDynamicAssembly(
                           myAsmName,
                           AssemblyBuilderAccess.RunAndSave);

        // The dynamic assembly space has been created.  Next, create a module
        // within it.  The type Point will be reflected into this module.

        ModuleBuilder myModuleBldr = myAsmBldr.DefineDynamicModule("MyModule");

        TypeBuilder myTypeBldr = myModuleBldr.DefineType("Adder");

        MethodBuilder myMthdBldr = myTypeBldr.DefineMethod("Add",
                                MethodAttributes.Public |
                                MethodAttributes.Static,
                                typeof(int),
                                new Type[]
                                {typeof(int), typeof(int)});
        // Build the array of Bytes holding the MSIL instructions.

     //   byte[] ILcodes = new byte[] {
     //         0x02,   /* 02h is the opcode for ldarg.0 */
        //  0x03,   /* 03h is the opcode for ldarg.1 */
        //  0x58,   /* 58h is the opcode for add     */
        //  0x2A    /* 2Ah is the opcode for ret     */
        //};

        var ILcodes = typeof(MethodBodyDemo).GetMethod("Add").GetMethodBody().GetILAsByteArray();

        myMthdBldr.CreateMethodBody(ILcodes, ILcodes.Length);

        addType = myTypeBldr.CreateType();

        return addType;
    }

    public static void TestExecMethod()
    {

        Type myType = BuildDynType();
        Console.WriteLine("---");
        Console.Write("Enter the first integer to add: ");
        int aVal = Convert.ToInt32(Console.ReadLine());

        Console.Write("Enter the second integer to add: ");
        int bVal = Convert.ToInt32(Console.ReadLine());

        object adderInst = Activator.CreateInstance(myType, new object[0]);

        Console.WriteLine("The value of adding {0} to {1} is: {2}.",
                   aVal, bVal,
                        myType.InvokeMember("Add",
                                 BindingFlags.InvokeMethod,
                                 null,
                                 adderInst,
                                 new object[] { aVal, bVal }));
    }

}

通过调用执行:

MethodBodyDemo.TestExecMethod();

有什么帮助吗?

我是做类似事情的图书馆的作者。 它读取现有方法的操作码,将其重新解释为通用操作码项,这些操作码项包含MethodInfo而不是带编号的标记,并从中构建方法副本。 这可以交叉组装,并且也适用于您的情况。

它设计为猴子打补丁游戏,但可以进行修改以将“明文”中的通用操作码传输到其他系统,以便目标可以进行类型查找,从而为本地程序集获取正确的操作码。

该项目获得MIT许可,被称为Harmony

Release模式下生成您的项目,然后执行以下任一操作:

在此处删除MethodAttributes.Static属性

MethodBuilder myMthdBldr = myTypeBldr.DefineMethod("Add",
                           MethodAttributes.Public |
                           MethodAttributes.Static,
                           typeof(int),
                           new Type[]
                           {typeof(int), typeof(int)});

或将此方法更改为static

public int Add(int x, int y)
{
    return x + y;
}

这应该为您工作。

在此处输入图片说明

但是 ,我在注释中看到您希望它将字节传递给其他系统并运行它,我的回答只是针对问题中的示例。 实际上,这是行不通的,因为西蒙·斯文森(Simon Svensson)发表评论的原因。 (除非所有方法都是静态方法,并且执行纯操作(如返回3 + 4),而不引用任何其他方法\\类型\\字段。)

从理论上讲,您仍然可以做一些魔术使它起作用,但是实际上并不可行。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM