使用反射清除所有挂在事件上的delegate
2007-03-23 13:00 by iceboundrock, 2851 visits, 网摘, 收藏, 编辑
在.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