有关 ILGenerator 的问题

问题描述

各位大大,小弟最近在研究使用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,"");}

虽不明,但觉厉。

时间: 2024-09-12 09:22:06

有关 ILGenerator 的问题的相关文章

emit的ILGenerator

在上一篇博客(说说emit(上)基本操作)中,我描述了基 本的技术实现上的需求,难度和目标范围都很小,搭建了基本的架子.在代码中 实现了程序集.模块.类型和方法的创建,唯一的缺憾是方法体. 方法体是方法内部的逻辑,我们需要将这个逻辑用IL代码描述出来,然后注入 到方法体内部.这里自然地引出两个主题,IL代码和用来将Il代码注入到方法体 内的工具(ILGenerator).本篇博客将主要围绕这两个主题展开.但是这一篇博 客不可能将IL讲的很详细,只能围绕ILGenerator的应用来讲解.若想了解

C#基础全接触

引用类型是类型安全的指针,它们的内存是分配在堆(保存指针地址)上的.String.数组.类.接口和委托都是引用类型.强制类型转换与as类型转换的区别:当类型转换非法时,强制类型转换将抛出一个System.InvalidCastException异常,而as不会抛出异常,它返回一个null值.用using创建别名:using console = System.Console;访问限定符:public  该成员可以被其他任何类访问protected 该成员只能被其派生类访问private  该成员只

通过Emit实现动态类生成

动态 动态生成一个类对于AOP,O/R Mapping等技术非常有帮助.对于Java来说,问题不大,而对于.NET,则要麻烦些(主要麻烦在于实现代码的生成需要IL),故猜测这可能也是在AOP, O/R Mapping方面,Java走得略前的原因吧. 麻烦归麻烦,非不能也,动态生成一个简单的类还不至于太难. 假设有如下接口: interface IAnimal { void move(); void eat(); } 希望能创建一个类生成器TypeCreator,并能以以下方式使用: TypeCr

emit的基本操作

最近收到<.NET 安全揭秘>的读者的邮件,提到了书中很多大家想看到的内 容却被弱化了,我本想回复很多内容因为书的主旨或者章节规划的原因只是概说 性的,但是转念一想,读者需要的,不正是作者该写的吗?因此我准备把邮件中 的问题一一搬到博客中,以博文的形式分享给大家. 今天要谈论的主题是Emit,反射的孪生兄弟.想要通过几篇博客详尽的讲解 Emit也是很困难的事情,本系列计划通过完成一个简单的Mock接口的功能来讲解 ,计划写三篇博客: 2)        说说Emit (中)ILGenerato

C#实现动态调用Windows DLL

调用方法: object obj = WinDllInvoke("Kernel32.dll", "Beep", new object[] { 750, 300 }, typeof(void)); 函数代码: 1 [System.Runtime.InteropServices.DllImport("kernel32")] 2 private static extern IntPtr LoadLibrary(string lpLibFileName)

挂载非引用Assembly中的事件

有两个 Assembly A,B 在A中声明了一个事件(某个类中的某个事件), B没有引用这 Assembly ,但是想挂A中的这个事件.当A中的某个逻辑fire这个Event时,B挂事件的地方要(B 的handler)要做些事情. FireFarEvent 是 Assembly A, MainForm 类公开一个 SomeEvent 事件, FireEvent button 会 Fire 这个 Event. AttachFarEvent 是 Assembly B, AttachFarEvent

Java中通过Emit实现动态类生成

动态生成一个类对于AOP,O/R Mapping等技术非常有帮助.对于Java来说,问题不大,而对于.NET,则要麻烦些(主要麻烦在于实现代码的生成需要IL),故猜测这可能也是在AOP, O/R Mapping方面,Java走得略前的原因吧. 麻烦归麻烦,非不能也,动态生成一个简单的类还不至于太难. 假设有如下接口: interface IAnimal { void move(); void eat(); } 希望能创建一个类生成器TypeCreator,并能以以下方式使用: TypeCreat

Emit学习-进阶篇-异常处理

异常的处理也是程序中比较重要的一个部分,今天我们就针对用IL书写异常处 理代码进行讲解,首先照例给出要实现的类的C#代码,如下: ExceptionHandler class ExceptionHandler { public static int ConvertToInt32(string str) { int num = 0; try { num = Convert.ToInt32(str); } catch (Exception ex) { Console.WriteLine(ex.Mes

Emit学习-基础篇-HelloWorld

按照业界的惯例,我们用一个最简单的例子--"Hello World",来开始我 们的Emit之旅.例子的相关代码及注释如下: using System; using System.Collections.Generic; using System.Text; using System.Reflection.Emit; namespace EmitExamples.HelloWorld { class Program { /// <summary> /// 用来调用动态方法的