轉自:http://www.cnblogs.com/caodajieup/archive/2011/09/29/2195117.html
在程式設計中有時候需要動態訂閱客戶自己的事件,調用完成後又要刪除以前訂閱的事件。因為如果不刪除,有時會造成事件是會重複訂閱,導致程式運行異常。一個辦法是用反射來控制項事件列表。清空方法代碼如下:
/// <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類型事件
}
這種方法可以一勞永逸,簡單方便。但由於引入了反射,涉及到的資料類型,編譯器是無法檢查的,容易給程式運行時帶來不穩定因素。
以上轉載的,我是要用來判斷ArcEngine中PageLayoutControl控制項的事件是否綁定處理函數的,由於MS事件機制的修改,已經不能通過==null的方式來判斷事件是否綁定函數了,需要用到反射,這個例子雖然短,不過剛好能說明情況
Type t = typeof(AxPageLayoutControl);
System.Reflection.FieldInfo fieldInfo = t.GetField("OnDoubleClick", myBindingFlags);
Delegate instanceDelegate = fieldInfo.GetValue(axPageLayoutControl1) as Delegate;
string msg = "";
if (instanceDelegate != null)
{
foreach (Delegate d in instanceDelegate.GetInvocationList())
{
//c.OnChange -= d as EventHandler;
////evt.RemoveEventHandler(c, d as EventHandler);
msg += d.Method.Name;
}
}
MessageBox.Show("deligate is:" + msg);
這樣就能把PageLayoutControl的OnDoubleClick綁定的所有函數的名稱輸出出來
可以進一步修改