在程序设计中有时候需要动态订阅客户自己的事件,调用完成后又要删除以前订阅的事件。因为如果不删除,有时会造成事件是会重复订阅,导致程序运行异常。一个办法是用反射来控件事件列表。清空方法代码如下:
/// <summary>
/// 清空控件的事件列表
/// </summary>
/// <param name="pControl">要清空事件列表的控件</param>
/// <param name="pEventName">事件名</param>
void ClearEvent(Control pControl, string pEventName)
{
if (pControl== null) return;
if (string.IsNullOrEmpty(pEventName)) return;
BindingFlags mPropertyFlags = BindingFlags.Instance | BindingFlags.Public
| BindingFlags.Static | BindingFlags.NonPublic;//筛选
BindingFlags mFieldFlags = BindingFlags.Static | BindingFlags.NonPublic;
Type controlType = typeof(System.Windows.Forms.Control);
PropertyInfo propertyInfo = controlType.GetProperty("Events", mPropertyFlags);
EventHandlerList eventHandlerList = (EventHandlerList)propertyInfo.GetValue(pControl, null);//事件列表
FieldInfo fieldInfo = (typeof(Control)).GetField("Event" + pEventName, mFieldFlags);
Delegate d = eventHandlerList[fieldInfo.GetValue(pControl)];
if (d == null) return;
EventInfo eventInfo=controlType.GetEvent(pEventName);
foreach (Delegate dx in d.GetInvocationList())
eventInfo.RemoveEventHandler(pControl, dx);//移除已订阅的pEventName类型事件
}
这种方法可以一劳永逸,简单方便。但由于引入了反射,涉及到的数据类型,编译器是无法检查的,容易给程序运行时带来不稳定因素。