加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – IL Emit用于调用委托实例?

发布时间:2020-12-15 08:16:00 所属栏目:百科 来源:网络整理
导读:基本上,我接受一个事件名称作为字符串,以获取EventInfo.然后,我使用反射发现事件处理程序类型和事件参数类型,创建该类型的新委托(myEventHandler),并将其与事件挂钩.当调用myEventHandler时,我需要向下转换并将参数传递给处理程序. 我的代码如下.当调用’d’
基本上,我接受一个事件名称作为字符串,以获取EventInfo.然后,我使用反射发现事件处理程序类型和事件参数类型,创建该类型的新委托(myEventHandler),并将其与事件挂钩.当调用myEventHandler时,我需要向下转换并将参数传递给处理程序.

我的代码如下.当调用’d’时,需要通过myEventHandler调用’handler’.我需要在那里放一些反射发射代码???有什么想法吗?

EventHandler handler = delegate(object sender,EventArgs eventArgs)
{
    //something will happen here                                
};

Type[] typeArgs = { typeof(object),derivedEventArgsType };

DynamicMethod myEventHandler = new DynamicMethod("",typeof(void),typeArgs);
var ilgen = myEventHandler.GetILGenerator();

//What should be the IL code here to 
//cast derviedEventArgs to EventArgs and
//invoke the 'handler' above??????
ilgen.Emit(OpCodes.Pop);
ilgen.Emit(OpCodes.Ret);



Delegate d = dynamic.CreateDelegate(derviedEventHandlerType);

//addMethod is the add MethodInfo for an Event
addMethod.Invoke(target,new object[] { d });

编辑:基于通过Reflector的观察.

反射器为手动编码的场景生成的代码是

.method public hidebysig instance void <Main>b__1(object sender,class ConsoleApplication2.MyEventArgs e) cil managed
{
    .maxstack 8
    L_0000: nop 
    L_0001: ldarg.0 
    L_0002: ldfld class [mscorlib]System.EventHandler ConsoleApplication2.Program/<>c__DisplayClass3::handler
    L_0007: ldarg.1 
    L_0008: ldarg.2 
    L_0009: callvirt instance void [mscorlib]System.EventHandler::Invoke(object,class [mscorlib]System.EventArgs)
    L_000e: nop 
    L_000f: ret 
}

这就是我在此基础上尝试的.

ilgen.Emit(OpCodes.Nop); 
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Ldfld,eh.GetType().GetField("handler"));
ilgen.Emit(OpCodes.Ldarg_1);
ilgen.Emit(OpCodes.Ldarg_2);
ilgen.EmitCall(OpCodes.Callvirt,eh.handler.Method,new Type[]{ typeof(object),typeof(EventArgs) });
ilgen.Emit(OpCodes.Nop);
ilgen.Emit(OpCodes.Ret);

但这会导致运行时错误:

‘Calling convention must be varargs’

可能我错过了一些东西,需要更好地了解IL.

解决方法

事实证明,我的事情过于复杂!巴里凯利 had the right idea:
static T CastDelegate<T>(Delegate src)
    where T : class
{
    return (T)(object)Delegate.CreateDelegate(
        typeof(T),src.Target,src.Method,true); // throw on fail
}

这适用于我的测试用例.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读