有关 ILGenerator 的问题

kslynn 2015-06-09 11:10:13
各位大大,小弟最近在研究 使用DynamicMethod创建动态代码,遇到疑问,具体如下:
新建一Window Form,命名为 Form1, 上面放置 button1,和 button2,
定义button1的Click事件为

private void button1_Click(object sender, EventArgs e)
{
object control = button2;
Type controltype = control.GetType();

EventInfo clickEvent = controltype.GetEvent("Click");
Type[] types = clickEvent.EventHandlerType.GetMethod("Invoke").GetParameters().Select(n => n.ParameterType).ToArray<Type>();

DynamicMethod method = new DynamicMethod("", null,types,controltype);
ILGenerator generator = method.GetILGenerator();

MethodInfo runmethod = typeof(MessageBox).GetMethod("Show", new Type[] { typeof(string) });
generator.Emit(OpCodes.Nop);
generator.Emit(OpCodes.Ldstr, "This is the Message needed to show!");
generator.Emit(OpCodes.Call, runmethod);
generator.Emit(OpCodes.Nop);
generator.Emit(OpCodes.Ret);
//
Delegate del = method.CreateDelegate(clickEvent.EventHandlerType);
clickEvent.GetAddMethod().Invoke(control, new object[] { del });
}

这样点击完button1后,点击button2,就会弹出 MessageBox
可是如果改为如下代码,就会运行错误。还请各位多多指教。

private void button1_Click(object sender, EventArgs e)
{
object control = button2;
Type controltype = control.GetType();

EventInfo clickEvent = controltype.GetEvent("Click");
Type[] types = clickEvent.EventHandlerType.GetMethod("Invoke").GetParameters().Select(n => n.ParameterType).ToArray<Type>();

DynamicMethod method = new DynamicMethod("", null,types,controltype);
ILGenerator generator = method.GetILGenerator();

MethodInfo runmethod = this.GetType().GetMethod("ShowMessage", BindingFlags.Instance | BindingFlags.NonPublic);
//runmethod = typeof(MessageBox).GetMethod("Show", new Type[] { typeof(string) });
generator.Emit(OpCodes.Nop);
generator.Emit(OpCodes.Ldstr, "This is the Message needed to show!");
generator.Emit(OpCodes.Call, runmethod);
generator.Emit(OpCodes.Nop);
generator.Emit(OpCodes.Ret);
//
Delegate del = method.CreateDelegate(clickEvent.EventHandlerType);
clickEvent.GetAddMethod().Invoke(control, new object[] { del });
}

void ShowMessage(string msg)
{
MessageBox.Show(msg, "");
}
...全文
344 11 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
kslynn 2015-06-11
  • 打赏
  • 举报
回复
貌似改为以下代码就成功了。


        private void button1_Click(object sender, EventArgs e)
        {
            object control = button2;
            Type controltype = control.GetType();

            EventInfo  clickEvent = controltype.GetEvent("Click");
            Type[] types = clickEvent.EventHandlerType.GetMethod("Invoke").GetParameters().Select(n => n.ParameterType).ToArray<Type>();

            DynamicMethod method = new DynamicMethod("", null,types,controltype);
            ILGenerator generator = method.GetILGenerator();

            MethodInfo runmethod = this.GetType().GetMethod("ShowMessage", BindingFlags.Instance | BindingFlags.NonPublic);
            //runmethod = typeof(MessageBox).GetMethod("Show", new Type[] { typeof(string) });
            generator.Emit(OpCodes.Nop);
            generator.Emit(OpCodes.Ldargs_0);
            generator.Emit(OpCodes.Ldstr, "This is the Message needed to show!");
            generator.Emit(OpCodes.Call, runmethod);
            generator.Emit(OpCodes.Nop);
            generator.Emit(OpCodes.Ret);
            //
            Delegate del = method.CreateDelegate(clickEvent.EventHandlerType);
            clickEvent.GetAddMethod().Invoke(control, new object[] { del });
        }

        void ShowMessage(string msg)
        {
            MessageBox.Show(msg, "");
        }

虽不明,但觉厉。
kslynn 2015-06-09
  • 打赏
  • 举报
回复

        void DynamicShowMsg(object control, string eventName)
        {
            Type controltype = control.GetType();

            EventInfo clickEvent = controltype.GetEvent(eventName);
            Type[] types = clickEvent.EventHandlerType.GetMethod("Invoke").GetParameters().Select(n => n.ParameterType).ToArray<Type>();

            DynamicMethod method = new DynamicMethod("", null, types, controltype);
            ILGenerator generator = method.GetILGenerator();

            MethodInfo runmethod = typeof(MessageBox).GetMethod("Show", new Type[] { typeof(string) });
            generator.Emit(OpCodes.Nop);
            generator.Emit(OpCodes.Ldstr, "This is the Message needed to show!");
            generator.Emit(OpCodes.Call, runmethod);
            generator.Emit(OpCodes.Pop);
            generator.Emit(OpCodes.Ret);
            //
            Delegate del = method.CreateDelegate(clickEvent.EventHandlerType);
            clickEvent.GetAddMethod().Invoke(control, new object[] { del });
        }
kslynn 2015-06-09
  • 打赏
  • 举报
回复
回二楼的话, 反射时可以把bindingFlag的 NonPublic加上就可以获取 非公有变量了。
kslynn 2015-06-09
  • 打赏
  • 举报
回复
把第一段代码中 generator.Emit(OpCodes.Ret); 前面那句换成 generator.Emit(OpCodes.Pop); 第一段就可以正常运行了。 抱歉,测试的代码没改过来。
超级小小 2015-06-09
  • 打赏
  • 举报
回复
测试了一下,LZ给的第一个代码就用不了,直接报错了。” JIT 编译器遇到内部限制。“豁我。
阿良良木月火 2015-06-09
  • 打赏
  • 举报
回复
引用 3 楼 mort464212863 的回复:
好吧,那我支持一下,学习一下,可否?删我信息的。
请最好不要在技术帖里面发与问题无关的回复,谢谢配合
超级小小 2015-06-09
  • 打赏
  • 举报
回复
好吧,那我支持一下,学习一下,可否?删我信息的。
於黾 2015-06-09
  • 打赏
  • 举报
回复
要用反射的话,被反射调用的函数要声明为public
kslynn 2015-06-09
  • 打赏
  • 举报
回复
期待各位精彩的回答
qq_16418239 2015-06-09
  • 打赏
  • 举报
回复
我也遇到同样的问题,顶个

111,097

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧