问题描述
各位大大,小弟最近在研究使用DynamicMethod创建动态代码,遇到疑问,具体如下:新建一WindowForm,命名为Form1,上面放置button1,和button2,定义button1的Click事件为privatevoidbutton1_Click(objectsender,EventArgse){objectcontrol=button2;Typecontroltype=control.GetType();EventInfoclickEvent=controltype.GetEvent("Click");Type[]types=clickEvent.EventHandlerType.GetMethod("Invoke").GetParameters().Select(n=>n.ParameterType).ToArray<Type>();DynamicMethodmethod=newDynamicMethod("",null,types,controltype);ILGeneratorgenerator=method.GetILGenerator();MethodInforunmethod=typeof(MessageBox).GetMethod("Show",newType[]{typeof(string)});generator.Emit(OpCodes.Nop);generator.Emit(OpCodes.Ldstr,"ThisistheMessageneededtoshow!");generator.Emit(OpCodes.Call,runmethod);generator.Emit(OpCodes.Nop);generator.Emit(OpCodes.Ret);//Delegatedel=method.CreateDelegate(clickEvent.EventHandlerType);clickEvent.GetAddMethod().Invoke(control,newobject[]{del});}
这样点击完button1后,点击button2,就会弹出MessageBox可是如果改为如下代码,就会运行错误。还请各位多多指教。privatevoidbutton1_Click(objectsender,EventArgse){objectcontrol=button2;Typecontroltype=control.GetType();EventInfoclickEvent=controltype.GetEvent("Click");Type[]types=clickEvent.EventHandlerType.GetMethod("Invoke").GetParameters().Select(n=>n.ParameterType).ToArray<Type>();DynamicMethodmethod=newDynamicMethod("",null,types,controltype);ILGeneratorgenerator=method.GetILGenerator();MethodInforunmethod=this.GetType().GetMethod("ShowMessage",BindingFlags.Instance|BindingFlags.NonPublic);//runmethod=typeof(MessageBox).GetMethod("Show",newType[]{typeof(string)});generator.Emit(OpCodes.Nop);generator.Emit(OpCodes.Ldstr,"ThisistheMessageneededtoshow!");generator.Emit(OpCodes.Call,runmethod);generator.Emit(OpCodes.Nop);generator.Emit(OpCodes.Ret);//Delegatedel=method.CreateDelegate(clickEvent.EventHandlerType);clickEvent.GetAddMethod().Invoke(control,newobject[]{del});}voidShowMessage(stringmsg){MessageBox.Show(msg,"");}
解决方案
解决方案二:
要用反射的话,被反射调用的函数要声明为public
解决方案三:
解决方案四:
好吧,那我支持一下,学习一下,可否?删我信息的。
解决方案五:
引用3楼mort464212863的回复:
好吧,那我支持一下,学习一下,可否?删我信息的。
请最好不要在技术帖里面发与问题无关的回复,谢谢配合
解决方案六:
测试了一下,LZ给的第一个代码就用不了,直接报错了。”JIT编译器遇到内部限制。“豁我。
解决方案七:
把第一段代码中generator.Emit(OpCodes.Ret);前面那句换成generator.Emit(OpCodes.Pop);第一段就可以正常运行了。抱歉,测试的代码没改过来。
解决方案八:
回二楼的话,反射时可以把bindingFlag的NonPublic加上就可以获取非公有变量了。
解决方案九:
voidDynamicShowMsg(objectcontrol,stringeventName){Typecontroltype=control.GetType();EventInfoclickEvent=controltype.GetEvent(eventName);Type[]types=clickEvent.EventHandlerType.GetMethod("Invoke").GetParameters().Select(n=>n.ParameterType).ToArray<Type>();DynamicMethodmethod=newDynamicMethod("",null,types,controltype);ILGeneratorgenerator=method.GetILGenerator();MethodInforunmethod=typeof(MessageBox).GetMethod("Show",newType[]{typeof(string)});generator.Emit(OpCodes.Nop);generator.Emit(OpCodes.Ldstr,"ThisistheMessageneededtoshow!");generator.Emit(OpCodes.Call,runmethod);generator.Emit(OpCodes.Pop);generator.Emit(OpCodes.Ret);//Delegatedel=method.CreateDelegate(clickEvent.EventHandlerType);clickEvent.GetAddMethod().Invoke(control,newobject[]{del});}
解决方案十:
我也遇到同样的问题,顶个
解决方案十一:
期待各位精彩的回答
解决方案十二:
貌似改为以下代码就成功了。privatevoidbutton1_Click(objectsender,EventArgse){objectcontrol=button2;Typecontroltype=control.GetType();EventInfoclickEvent=controltype.GetEvent("Click");Type[]types=clickEvent.EventHandlerType.GetMethod("Invoke").GetParameters().Select(n=>n.ParameterType).ToArray<Type>();DynamicMethodmethod=newDynamicMethod("",null,types,controltype);ILGeneratorgenerator=method.GetILGenerator();MethodInforunmethod=this.GetType().GetMethod("ShowMessage",BindingFlags.Instance|BindingFlags.NonPublic);//runmethod=typeof(MessageBox).GetMethod("Show",newType[]{typeof(string)});generator.Emit(OpCodes.Nop);generator.Emit(OpCodes.Ldargs_0);generator.Emit(OpCodes.Ldstr,"ThisistheMessageneededtoshow!");generator.Emit(OpCodes.Call,runmethod);generator.Emit(OpCodes.Nop);generator.Emit(OpCodes.Ret);//Delegatedel=method.CreateDelegate(clickEvent.EventHandlerType);clickEvent.GetAddMethod().Invoke(control,newobject[]{del});}voidShowMessage(stringmsg){MessageBox.Show(msg,"");}
虽不明,但觉厉。