使用反射清除所有掛在事件上的delegate
來源:互聯網
上載者:User
在.net中,event是一個相當有用的特性,它讓我們可以很輕鬆的實現回調。但是它也有著相當的不方便之處:一個event在聲明它的class之外只能使用+=/-=操作符進行delegate的增減,無法一次刪除所有掛在它上面的delegate。
程式規模小的時候還好辦,一旦程式膨脹,想弄清到底在一個事件上掛了那些delegate還真是挺麻煩的事情。尤其是很多class都有事件,很多事件在不同的地方被掛鈎。當確定一個對象不用的時候,你需要及時把它的事件上掛的delegate斷開。
下面這個函數可以起到直接清空一個對象所有的事件的作用,還是老規矩,代碼就不多解釋了: 1 /// <summary>
2 /// 清除一個對象所有事件所掛鈎的delegate
3 /// </summary>
4 /// <param name="objectHasEvents">有事件的對象</param>
5 public static void ClearAllEvents(object objectHasEvents)
6 {
7 if (objectHasEvents == null)
8 {
9 return;
10 }
11
12 EventInfo[] events = objectHasEvents.GetType().GetEvents(
13 BindingFlags.Public |
14 BindingFlags.NonPublic |
15 BindingFlags.Instance);
16
17 if (events == null || events.Length < 1)
18 {
19 return;
20 }
21
22 for (int i = 0; i < events.Length; i++)
23 {
24 try
25 {
26 EventInfo ei = events[i];
27
28 /********************************************************
29 * class的每個event都對應了一個同名的private的delegate類
30 * 型成員變數(這點可以用Reflector證實)。因為private成
31 * 員變數無法在基類中進行修改,所以為了能夠拿到base
32 * class中聲明的事件,要從EventInfo的DeclaringType來擷取
33 * event對應的成員變數的FieldInfo並進行修改
34 ********************************************************/
35 FieldInfo fi =
36 ei.DeclaringType.GetField(ei.Name,
37 BindingFlags.NonPublic |
38 BindingFlags.Instance);
39 if (fi != null)
40 {
41 // 將event對應的欄位設定成null即可清除所有掛鈎在該event上的delegate
42 fi.SetValue(objectHasEvents, null);
43 }
44 }
45 catch
46 {
47 }
48 }
49 }
50
51