博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用反射将委托挂钩
阅读量:4134 次
发布时间:2019-05-25

本文共 4005 字,大约阅读时间需要 13 分钟。

using System;

using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Reflection;
using System.Reflection.Emit;

namespace EmitHandler

{
    public class Example
    {
        /// <summary>
        /// 使用反射将委托挂钩
        /// </summary>
        /// <param name="outputBlock"></param>
        public static void Demo(System.Windows.Controls.TextBlock outputBlock)
        {
            // 获取某一未知对象,或者创建在您已加载的程序集中找到的类型的对象。
            // 为使示例简单,使用的对象是为示例的输出提供的 TextBlock;
            // 但是,TextBlock 存储为 Object 类型,以保持对该对象或其来自的程序集一无所知的状态
            object obj = outputBlock;

            // 获取表示该事件的 EventInfo 对象,并使用 EventHandlerType 属性来获取用于处理事件的委托类型。

            // 在下面的代码中,获取了 MouseLeftButtonUp 事件的 EventInfo。
            // 此示例按名称查找事件,但可以使用 Type.GetEvents 方法来查看存在哪些事件
            //foreach(EventInfo ei in outputBlock.GetType().GetEvents())
            //{
            //    outputBlock.Text += ei.Name+"\n";
            //}

            //Type opb = typeof(TextBlock);

            //foreach (MethodInfo ei in opb.GetMethods())

            //{
            //    //if (ei.Name.StartsWith("g"))
            //    outputBlock.Text += ei.Name + "\n";
            //}

 

            EventInfo evMouseUp = outputBlock.GetType().GetEvent("MouseLeftButtonUp");
            Type tEenType = evMouseUp.EventHandlerType;

            // If you already have a method with the correct signature,

            // you can simply get a MethodInfo for it.
            //
            MethodInfo miHandler =
               typeof(Example).GetMethod("LuckyHandler",
                             BindingFlags.NonPublic | BindingFlags.Static);
           
            // 创建委托实例.
           
            Delegate d = Delegate.CreateDelegate(tEenType, miHandler);

            //获取 add 访问器方法,并调用该方法以将事件挂钩。

            //所有事件都具有一个 add 访问器或 remove 访问器,这些访问器被高级语言的语法隐藏。
            //例如,C# 使用 += 运算符将事件挂钩,而 Visual Basic 则使用 AddHandler 语句。
            //下面的代码获取 MouseLeftButtonUp 事件的 add 访问器并以后期绑定方式调用它,并在委托实例中传递。
            //参数必须作为数组传递
            MethodInfo miAddHandler = evMouseUp.GetAddMethod();
            object[] addHandlerArgs = { d };
            miAddHandler.Invoke(obj, addHandlerArgs);
            //outputBlock.Text += "Click here to invoke the two delegates.\n";

            // 使用轻量动态方法和反射发出可在运行时生成事件处理程序方法。
            // 若要构造事件处理程序,您需要知道返回类型和委托的参数类型。
            // 可以通过检查委托的 Invoke 方法来获取这些类型。下
            // 面的代码使用 GetDelegateReturnType 和 GetDelegateParameterTypes 方法通过反射获取此信息。
           
            Type returnType = GetDelegateReturnType(tEenType);
            if (returnType != typeof(void))
            {
                throw new InvalidOperationException("Delegate has a return type.");
            }

            DynamicMethod handler =

               new DynamicMethod("", null, GetDelegateParameterTypes(tEenType));

            // 生成方法体。

            //此方法加载字符串、
            //调用带有单个字符串的 Show 方法重载、
            //从堆栈弹出返回值(因为处理程序没有返回类型)并返回这些值.
            ILGenerator ilgen = handler.GetILGenerator();

            Type[] showParameters = { typeof(string) };

            MethodInfo miShow =
               typeof(System.Windows.MessageBox).GetMethod("Show", showParameters);

            //推送对元数据中存储的字符串的新对象引用

            ilgen.Emit(OpCodes.Ldstr, "This event handler was constructed at run time.");
            //调用方法
            ilgen.Emit(OpCodes.Call, miShow);
            //出栈
            ilgen.Emit(OpCodes.Pop);
            //返回
            ilgen.Emit(OpCodes.Ret);

            Delegate dEmitted = handler.CreateDelegate(tEenType);
            evMouseUp.AddEventHandler(obj, dEmitted);

            // Clicking on the TextBlock now causes the two delegates to

            // be invoked.
            //
            outputBlock.Text += "Click here to invoke the two delegates.\n";
        }

        private static void LuckyHandler(object sender, EventArgs e)

        {
            System.Windows.MessageBox.Show(
               "This event handler just happened to be lying around.");
        }

        private static Type[] GetDelegateParameterTypes(Type d)

        {
            if (d.BaseType != typeof(MulticastDelegate))
            {
                throw new InvalidOperationException("Not a delegate.");
            }

            MethodInfo invoke = d.GetMethod("Invoke");

            if (invoke == null)
            {
                throw new InvalidOperationException("Not a delegate.");
            }

            ParameterInfo[] parameters = invoke.GetParameters();

            Type[] typeParameters = new Type[parameters.Length];
            for (int i = 0; i < parameters.Length; i++)
            {
                typeParameters[i] = parameters[i].ParameterType;
            }

            return typeParameters;

        }

        private static Type GetDelegateReturnType(Type d)
        {
            if (d.BaseType != typeof(MulticastDelegate))
            {
                throw new InvalidOperationException("Not a delegate.");
            }

            MethodInfo invoke = d.GetMethod("Invoke");

            if (invoke == null)
            {
                throw new InvalidOperationException("Not a delegate.");
            }

            return invoke.ReturnType;

        }

    }

}

转载地址:http://nvpvi.baihongyu.com/

你可能感兴趣的文章
Linux下使用VIM实现批量注释的方法
查看>>
Oracle 设置表空间自增长
查看>>
本地电脑与远程桌面无法复制粘贴怎么办
查看>>
Linux中对逻辑卷进行扩容与缩小
查看>>
在hadoop调用mapreduce对文件中各个单词出现次数进行统计
查看>>
RDD编程初级实践
查看>>
每日一题 错选择 及 编程题 周总结(五)
查看>>
举例详解 java.util.concurrent 并发包 4 种常见类
查看>>
Web在线聊天室(完结) --- 注册用户+ip地址
查看>>
求正数数组的最小不可组成和 --- 背包问题(动态规划)
查看>>
思维导图模式 -- 深度理解及复习 数据库 知识
查看>>
思维导图模式 -- 深度理解及复习 JavaWeb 知识
查看>>
初识Spring(IOC,DI,创建流程)
查看>>
初识Spring Framework——Bean、注册Bean、依赖注入
查看>>
思维导图模式 -- 深度理解及复习 网络 知识
查看>>
SpringBoot使用Redis做缓存,RedisUtil
查看>>
为什么你们这么喜欢在for循环里面增删改查!
查看>>
JAVA -敏感词过滤器 工具类SensitiveFilter
查看>>
JAVA 订单号生成类
查看>>
JAVA - 根据用户自增ID生成邀请码的工具类
查看>>