Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/281.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 通过Emit(Opcodes.Call,methodinfo)创建类型的实例_C#_Reflection_Cil_Il - Fatal编程技术网

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

C# 通过Emit(Opcodes.Call,methodinfo)创建类型的实例,c#,reflection,cil,il,C#,Reflection,Cil,Il,我正在使用反射和ilGenerator创建一个.Exe,从DLL调用一个方法 我的问题是,当它是一个实例方法时,我必须在调用该方法之前将实例放入堆栈中。因此,我在C#中有一个方法,它创建并返回这个实例。它正在抛出System.MethodAccessException 我的问题是,这可能吗?它是如何工作的?通过在IL中执行此操作,IL.Emit(Opcodes.call,methodInfo),在创建.exe的调用中,在运行时,它如何知道要调用哪个方法?我要调用的方法是否转到.exe程序集?我对

我正在使用反射和ilGenerator创建一个.Exe,从DLL调用一个方法

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

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

我转到DLL,获取类型,获取我要调用的
MethodInfo
。 我创建了一个新的程序集->组装生成器->模块生成器->类型生成器我创建的这个新类型是从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");
它正在抛出
System.MethodAccessException

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

在创建.exe的调用中,当处于运行时,它如何知道要调用哪个方法

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


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

向下投票人:请发表评论。你能展示一下你正在做什么来获得
MethodAccessException
?我很难按照问题中的描述进行操作。是的,你可以向下投票,但至少要说明原因,我现在要编辑为你的问题创建高级代码,编译它,然后使用类似的工具查看生成的IL。