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

标签 c# reflection cil il

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

我的问题是当它是一个实例方法时,我必须在调用方法之前将实例放入堆栈。因此我在 C# 中有一个方法,它创建并返回这个实例。它正在抛出 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.

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

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

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

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

关于c# - 通过 Emit(Opcodes.Call, methodinfo) 创建一个类型的实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33394453/

相关文章:

c# - 在 C# 中使用 Windows 默认编辑器打开图像

c# - 如何从具有 n 个子项/子项等的 CustomObject 中获取所有子对象

c# - 检查 C# 中的任何 int 类型?

.net - MSIL代码问题

c# - 在 Mono : invalid conversion of function? 中将 C++ 公开给 C#

c# - sqlite错误WP8.1

c# - 指定存储在列表数组中的每个列表的初始容量

java - 如何在 Java 中获取给定类的数组类?

reflection - 在 PHPUnit 中使用反射

c# - 为什么这段代码无法验证?