通过CIL DynamicMethod调用方法

问题描述

我正在尝试通过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

动态方法的C#代码/ il

        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,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>));

在这种情况下,您应该在Pop之前删除Ret指令。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...