我使用Reflection和ilGenerator来创建一个从DLL调用方法的.Exe。
我的问题是当它是一个实例方法时,我必须在调用方法之前将实例放入堆栈。因此我在C#中有一个方法,它创建并返回此实例。它正在抛出System.MethodAccessException
。
我的问题是,这甚至可能吗?它是如何工作的?通过在IL,il.Emit(Opcodes.call, methodInfo)
中执行此操作,在创建.exe的调用中,在运行时,它如何知道要调用哪种方法?我想调用的方法是否转到.exe程序集?我很困惑。
我转到DLL,获取类型,获取我要调用的MethodInfo
。
我创建了一个新的Assembly-> AssemblyBuilder-> ModuleBuilder-> TypeBuilder这个我正在创建的新类型是从DLL扩展Type:
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");
答案 0 :(得分:2)
投掷
System.MethodAccessException
。
您是否正在尝试调用通常对您正在生成的类型可见的方法(调用私有或内部方法,在您不继承的类中调用受保护的方法)。我相信通过禁用验证是可能的,但如果您需要在部分信任环境中运行,则会增加代码的安全性要求,这是一个问题。
在创建.exe的调用中,在运行时,它如何知道要调用哪种方法?
发出的IL包含一个4字节的元数据标记,这实际上是对生成的模块(MethodDef或MemberRef表)中的一个元数据表中的记录的引用。如果它是MethodDef令牌,那么它是对方法定义的直接引用,如果它是一个MemberRef令牌,那么它将提供足够的信息来识别要调用的正确的程序集/类/方法。
生成IL的代码表示您使用了调用操作码。如果你正在调用一个虚方法,那么你应该使用callvirt(虽然你可以使用非抽象方法调用,它会导致调用特定的实现......即使它被覆盖,这可能是意外的,我读了在某个地方添加了对另一个对象的虚拟方法使用调用的安全性要求。)