我正试图通过il调用一个方法,尽管指令似乎是正确的,但我得到了一个System.Security.VerificationException:"操作可能会破坏运行时的稳定。">
呼叫看起来像var a = Configuration.JsonHandler.Deserialize(typeof(Dictionary<string, object>), "{}")
使用ILDASM生成以下指令:
.method private hidebysig static void Run() cil managed
{
// Code size 27 (0x1b)
.maxstack 8
IL_0000: call class IJsonHandler Configuration::get_JsonHandler()
IL_0005: ldtoken class [mscorlib]System.Collections.Generic.Dictionary`2<string,object>
IL_000a: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_000f: ldstr "{}"
IL_0014: callvirt instance object IJsonHandler::Deserialize(class [mscorlib]System.Type,string)
IL_0019: pop
IL_001a: ret
} // end of method Program::Run
动态方法/il 的c#代码
var jHandlerGetter = typeof(Configuration).GetProperties().Where(p => p.PropertyType == typeof(IJsonHandler)).Select(p => p.GetGetMethod()).First();
var deserializeMethod = Configuration.JsonHandler.GetType().GetMethod("Deserialize");
var dynamicMethod = new DynamicMethod("DynamicMethod", null, null, true);
var il = dynamicMethod.GetILGenerator();
il.Emit(OpCodes.Call, jHandlerGetter);
il.Emit(OpCodes.Ldtoken, typeof(Dictionary<string, string>));
il.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle"));
il.Emit(OpCodes.Ldstr, "{}");
il.Emit(OpCodes.Callvirt, deserializeMethod);
il.Emit(OpCodes.Pop);
il.Emit(OpCodes.Ret);
var action = (Action)dynamicMethod.CreateDelegate(typeof(Action));
action();
使用il可视化工具,我可以看到上面生成的完全相同的指令。
IL_0000: call IJsonHandler get_JsonHandler()/Configuration
IL_0005: ldtoken System.Collections.Generic.Dictionary`2[System.String,System.String]/
IL_000a: call System.Type GetTypeFromHandle(System.RuntimeTypeHandle)/System.Type
IL_000f: ldstr "{}"
IL_0014: callvirt System.Object Deserialize(System.Type, System.String)/JHandler
IL_0019: pop
IL_001a: ret
谁能告诉我我做错了什么??
Operation could destabilize the runtime.
错误是由您试图获取MethodInfo的错误类型引起的。您必须使用接口类型而不是实现。
像这样:
var deserializeMethod = typeof(IJsonHandler).GetMethod("Deserialize");
我还假设您希望返回Deserialize()
的结果,所以您应该在动态方法声明中这样说:
var dynamicMethod = new DynamicMethod("DynamicMethod", typeof(object), null, true);
并相应地更改委托创建:
var func = (Func<object>)dynamicMethod.CreateDelegate(typeof(Func<object>));
在这种情况下,应该在Ret
之前删除Pop
指令。