这个方法应该是最全面的了,写这个的初衷是为了注销事件所绑定的静态事件方法,避免内存泄露.
但是网上的大多只有一个粗略的获取 EventHandlerList 的方法,对于复杂情况的自定义类或者派生类无法准确获取.
this object control 用 object 是为了兼容自定义类里的事件
/// <summary>
/// 清空控件所有事件的处理方法.
/// 默认过滤掉 "Disposed"
/// </summary>
/// <param name="control"></param>
/// <param name="fifterEvents">需要跳过的事件,事件名包含即可,不区分大小写</param>
public static void ClearEvent(this object control, List<string> fifterEvents)
{
var type = control.GetType();
var events = type.GetEvents();
foreach(var evt in events)
{
if (fifterEvents != null && fifterEvents.Any(f => evt.Name.IndexOf(f, StringComparison.OrdinalIgnoreCase) > -1))
continue;
var InvocationList = control.GetEventInvocationList(evt.Name);
if (InvocationList == null || InvocationList.Length == 0)
continue;
foreach(var deleg in InvocationList)
{
evt.RemoveEventHandler(control, deleg);
}
}
}
/// <summary>
/// 清空控件指定事件下的事件处理方法
/// </summary>
/// <param name="control"></param>
/// <param name="eventname"></param>
public static void ClearEvent(this object control, string eventname)
{
var InvocationList = control.GetEventInvocationList(eventname);
if (InvocationList == null)
return;
Type controlType = control.GetType();
EventInfo eventInfo = controlType.GetEvent(eventname);
foreach (Delegate dx in InvocationList)
eventInfo.RemoveEventHandler(control, dx);
}
/// <summary>
/// 手动触发控件的指定事件
/// </summary>
/// <param name="control"></param>
/// <param name="eventname"></param>
/// <param name="e">事件参数,一般第一个参数sender默认为控件,所以就省略了,只需要传第二个参数</param>
public static void TriggerEvent(this object control, string eventname, object e)
{
var InvocationList = control.GetEventInvocationList(eventname);
if (InvocationList == null)
return;
foreach (Delegate dx in InvocationList)
dx.DynamicInvoke(control, e);
}
/// <summary>
/// 获取指定事件的委托
/// </summary>
/// <param name="control"></param>
/// <param name="eventname"></param>
/// <returns></returns>
public static Delegate[] GetEventInvocationList(this object control, string eventname)
{
if (control == null) return null;
if (string.IsNullOrEmpty(eventname)) return null;
Type controlType = control.GetType();
return GetEventInvocationList(control, controlType, eventname);
}
public static Delegate[] GetEventInvocationList(this object control, Type controlType, string eventname)
{
if (string.IsNullOrEmpty(eventname)) return null;
BindingFlags mPropertyFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.IgnoreCase;
BindingFlags mFieldFlags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.IgnoreCase;
PropertyInfo propertyInfo = controlType.GetProperty("Events", mPropertyFlags);
if (propertyInfo == null)
{
if (controlType.BaseType.FullName == "System.Object")
return null;
return GetEventInvocationList(control, controlType.BaseType, eventname);
}
EventHandlerList eventHandlerList = (EventHandlerList)propertyInfo.GetValue(control, null);
FieldInfo fieldInfo = controlType.GetField("Event" + eventname, mFieldFlags);
if (fieldInfo == null) fieldInfo = controlType.GetField("Event_" + controlType.Name + eventname, mFieldFlags);//有的控件时需要加上控件类型名作为事件名,
if (fieldInfo == null) fieldInfo = controlType.GetField(eventname, mFieldFlags);//也许有的不需要加前缀
if (fieldInfo == null)
{
//有的必须递归从 BaseType 才能取到事件字段
if (controlType.BaseType.FullName == "System.Object")
return null;
return GetEventInvocationList(control, controlType.BaseType, eventname);
}
var fieldInfoValue = fieldInfo.GetValue(control);
Delegate d = eventHandlerList[fieldInfoValue];
if (d == null) return null;
return d.GetInvocationList();
}