通过 Emit(Opcodes.Call, methodinfo) 创建一个类型的实例

Create an Instance of a Type, via Emit(Opcodes.Call, methodinfo)

我正在使用 Reflection 和 ilGenerator 创建一个从 DLL 调用方法的 .Exe。

我的问题是当它是一个实例方法时,我必须在调用方法之前将实例放入堆栈。因此我在 C# 中有一个方法,它创建并 returns 这个实例。它正在投掷 System.MethodAccessException.

我的问题是,这可能吗?它是如何工作的?通过在 IL il.Emit(Opcodes.call, methodInfo) 中执行此操作,在创建 .exe 的调用中,在运行时,它如何知道要调用什么方法?我要调用的方法是否转到 .exe 程序集?我对此很困惑。

我去DLL,获取类型,获取我要调用的MethodInfo。 我创建了一个新的 Assembly->AssemblyBuilder->ModuleBuilder->TypeBuilder 我正在创建的这个新类型是从 DLL 扩展类型:

 TypeBuilder tb = mb.DefineType("TypeApp" + typeName, baseType.Attributes, DLLType);

我创建 MethodBuilder 作为新类型的入口点:

MethodBuilder metb = tb.DefineMethod("Main", MethodAttributes.Public |
            MethodAttributes.Static, typeof(void), argsArray);
ab.SetEntryPoint(metb);

然后我为 Main 方法生成 IL:

ILGenerator il = metb.GetILGenerator();

il.Emit(OpCodes.Call, callcreateInstanceMethodInfo);

IL 继续,但到目前为止我还没有完全理解这一点...

然后我创建 .exe

 tb.CreateType();
 ab.Save(typeName + methodName + ".exe");

It is throwing System.MethodAccessException.

您是否正在尝试调用您正在生成的类型通常不可见的方法(调用私有或内部方法,在您不继承自的 class 中调用受保护的方法)。我相信通过禁用验证是可能的,但这会增加代码的安全要求,如果您需要在部分信任环境中 运行,这将是一个问题。

in the call that creates the .exe, when in runtime, how does it know what method to call?

发出的 IL 包含一个 4 字节的元数据标记,这实质上是对生成模块中元数据 table 之一的记录的引用(MethodDef 或 MemberRef table ).如果它是 MethodDef 令牌,那么它是对方法定义的直接引用,如果它是 MemberRef 令牌,那么它将提供足够的信息来识别要调用的正确 assembly/class/method。

您显示的生成 IL 的代码表明您正在使用调用操作码。如果您正在调用虚拟方法,那么您应该改用 callvirt(尽管您可以对非抽象方法使用调用,但它会导致调用特定的实现......即使它被重写,这也可能是意想不到的,我读到某处对使用调用另一个对象的虚拟方法增加了安全要求)。