码迷,mamicode.com
首页 > 其他好文 > 详细

清除事件所有委托方法

时间:2017-11-30 19:16:38      阅读:187      评论:0      收藏:0      [点我收藏+]

标签:static   src   img   com   ring   flags   移除   报表开发   fast   

问题背景

在做winform报表开发时,FastReport是一个很好的工具,它提供了一些封装好的控件,可以很方便快速的开发打印报表。其中有一个控件是用于预览报表的,所有功能按钮事件方法都是封装好的。

技术分享图片

一般情况下这些功能按钮封装好的事件能满足基本的使用,不需要写多余的代码,但是在实际使用过程中,经常会遇到一些需要保存打印记录等操作情景,原有的按钮事件无法满足,就有了需要替换掉原按钮事件调用的方法的需求。

解决方案

因为控件是封装好的,无法直接知道事件具体调用哪些方法,通过 -= 的方式取消订阅事件,于是便想到了反射,通过反射将该事件的调用列表获取出来,然后全部清除掉,再通过 += 的方式订阅自定义方法。经过一番资料查找,整理出了一个帮助类:

 public static class EventHelper
 {
        private const BindingFlags BINDINGFLAGS = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.Static;

        /// <summary>
        /// 获取事件委托调用列表
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="obj">事件所属对象</param>
        /// <param name="eventName">事件名称</param>
        /// <returns></returns>
        public static Delegate[] GetInvocationList<T>(this T obj, string eventName) where T : class
        {
            if (obj == null || string.IsNullOrEmpty(eventName))
            {
                return null;
            }
            var eventInfo = obj.GetType().GetEvent(eventName);
            if (eventInfo == null)
            {
                return null;
            }
            Delegate d = null;
            var fieldInfo = eventInfo.DeclaringType.GetField(eventName, BINDINGFLAGS);
            if (fieldInfo != null)
            {
                d = (Delegate)fieldInfo.GetValue(obj);
                return d == null ? null : d.GetInvocationList();
            }
            fieldInfo = eventInfo.DeclaringType.GetField("Event" + eventName, BINDINGFLAGS);
            if (fieldInfo == null)
            {
                fieldInfo = eventInfo.DeclaringType.GetField("EVENT_" + eventName.ToUpper(), BINDINGFLAGS);
            }
            if (fieldInfo == null)
            {
                return null;
            }
            PropertyInfo propertyInfo = obj.GetType().GetProperty("Events", BINDINGFLAGS);
            EventHandlerList eventHandlerList = (EventHandlerList)propertyInfo.GetValue(obj, null);
            d = eventHandlerList[fieldInfo.GetValue(obj)];
            return d == null ? null : d.GetInvocationList();
        }

        /// <summary>
        /// 清除事件委托调用列表
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="obj">事件所属对象</param>
        /// <param name="eventName">事件名称</param>
        public static void ClearInvocationList<T>(this T obj, string eventName) where T : class
        {
            var handlers = obj.GetInvocationList(eventName);
            if (handlers == null)
            {
                return;
            }
            var eventInfo = obj.GetType().GetEvent(eventName);
            foreach (var handler in handlers)
            {
                eventInfo.RemoveEventHandler(obj, handler);//移除已订阅的eventName类型事件
            }
        }
   }

通过这个帮助类,可以方便的获取或清除事件的调用列表,使用方式如下:

button.GetInvocationList("Click");
button.ClearInvocationList("Click");

 

PS:学业不精,有些专业知识理解的不是很透彻,术语maybe不正确导致阅读理解错误,大神不理赐教。

清除事件所有委托方法

标签:static   src   img   com   ring   flags   移除   报表开发   fast   

原文地址:http://www.cnblogs.com/huangzhenhua/p/7930340.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!