清除事件所有委托方法
阿新 • • 發佈:2017-11-30
出了 使用方式 直接 多余 his ima oid cas 分享圖片
問題背景
在做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不正確導致閱讀理解錯誤,大神不理賜教。
清除事件所有委托方法