c# - 如何在对驻留在不同程序集中的方法执行 JMP 指令时获取正确的方法引用

标签 c# .net-assembly reflection.emit il

我有以下代码,基本上创建了一个包含 2 种类型的 DynamicAssembly,每种类型都有一个公共(public)方法。

        var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly
                (new AssemblyName("TestAssembly"), AssemblyBuilderAccess.Run);
        var module = assembly.DefineDynamicModule("Main");
        var type1 = module.DefineType("type1");


        var method1 = type1.DefineMethod
                      (
                        "Method1", MethodAttributes.Public, typeof(void), null
                      );

        var gen = method1.GetILGenerator();
        gen.Emit(OpCodes.Ret);

        var t1 = type1.CreateType();

        var createdMethod1 = t1.GetMethod("Method1");

        var type2 = module.DefineType("type2");

        var method2 = type2.DefineMethod
                      (
                        "Method2", MethodAttributes.Public, typeof(void), null
                      );


        byte[] ilCodes = new byte[5];
        ilCodes[0] = (byte)OpCodes.Jmp.Value;
        ilCodes[1] = (byte)(createdMethod1.MetadataToken & 0xFF);
        ilCodes[2] = (byte)(createdMethod1.MetadataToken >> 8 & 0xFF);
        ilCodes[3] = (byte)(createdMethod1.MetadataToken >> 16 & 0xFF);
        ilCodes[4] = (byte)(createdMethod1.MetadataToken >> 24 & 0xFF);

        method2.SetMethodBody(ilCodes, ilCodes.Length, null, null, null);


        var obj = Activator.CreateInstance(type2.CreateType());

        obj.GetType().GetMethod("Method2").Invoke(obj, null);

每当我调用 type2.method2() 时,我都会有一条 JMP 指令指向 type1.method1()。

这就像一个魅力,两种类型都位于同一个程序集中。

现在,如果我想重定向到另一个程序集中的类型,我如何才能获得正确的程序集/模块引用以使 JMP 指令成功。如果我只是这样做:

        byte[] ilCodes = new byte[5];
        ilCodes[0] = (byte)OpCodes.Jmp.Value;
        ilCodes[1] = (byte)(methodFromOtherAssembly.MetadataToken & 0xFF);
        ilCodes[2] = (byte)(methodFromOtherAssembly.MetadataToken >> 8 & 0xFF);
        ilCodes[3] = (byte)(methodFromOtherAssembly.MetadataToken >> 16 & 0xFF);
        ilCodes[4] = (byte)(methodFromOtherAssembly.MetadataToken >> 24 & 0xFF);

它一直失败并出现 IndexNotFound 异常。

我想用 Raw IL 字节指令来做这件事。

最佳答案

元数据 token 不是全局唯一的。它们在调用方法模块的上下文中解析。您需要使用 GetMetadataToken在模块上获取正确的 token 。您的第一个示例有效,因为这些方法共享同一个模块。

这将从动态模块中获取正确的 token :

byte[] ilCodes = new byte[5];
int token = module.GetMetadataToken(methodFromOtherAssembly).Token;
ilCodes[0] = (byte)OpCodes.Jmp.Value;
ilCodes[1] = (byte)(token & 0xFF);
ilCodes[2] = (byte)(token >> 8 & 0xFF);
ilCodes[3] = (byte)(token >> 16 & 0xFF);
ilCodes[4] = (byte)(token >> 24 & 0xFF);

关于c# - 如何在对驻留在不同程序集中的方法执行 JMP 指令时获取正确的方法引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31278912/

相关文章:

c# - 我有 3 个任务,我希望它们同时开始并并行运行

c# - Selenium2 Webdriver C# .Click() 列表 - 陈旧引用异常

c# - VS2012 模板向导 - GUI 未显示

java - C# 从类型创建类的实例

c# - Reflection.Emit 泛型基类泛型方法调用

c# - DatagridView 不显示水平滚动条

c# - 如何从excel导入documentDB中的批量数据?

c# - 如何让 CLR 知道从 GAC 选择哪个程序集?

c# - 在新应用程序域上创建动态程序集

c# - 从 IL 构造方法引用集合