如何通过反射清空类中所有静态事件的已注册处理程序?
解决方案
方法1:直接清空事件后台委托字段(推荐,实现最简单性能最高)
C#中你写的这种字段式声明的事件,编译器会自动生成一个和事件同名的私有静态委托字段作为存储,直接通过反射把该字段赋值为null即可清空所有订阅:
using System.Reflection; public static void ResetEvents() { Type type = typeof(ClientEvents); // 遍历所有公开静态事件 EventInfo[] events = type.GetEvents(BindingFlags.Static | BindingFlags.Public); foreach (EventInfo eventInfo in events) { // 获取编译器生成的后台委托字段,字段名和事件名一致 FieldInfo field = type.GetField( eventInfo.Name, BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public ); if (field != null && field.FieldType.BaseType == typeof(Delegate)) { // 静态成员不需要实例,直接将委托字段设为null即可清空所有订阅 field.SetValue(null, null); } } }
注意事项:
- 该方法适用于你当前代码里的常规字段式事件声明场景,如果你自定义了事件的
add/remove访问器,需要根据自定义存储逻辑调整。
方法2:使用RemoveEventHandler标准API移除(兼容性更强)
如果你担心不同编译器生成的后台字段名存在差异,可以用标准事件API先获取所有订阅委托,再逐一移除:
using System.Reflection; public static void ResetEvents() { Type type = typeof(ClientEvents); EventInfo[] events = type.GetEvents(BindingFlags.Static | BindingFlags.Public); foreach (EventInfo eventInfo in events) { // 获取事件当前绑定的所有委托 FieldInfo field = type.GetField(eventInfo.Name, BindingFlags.Static | BindingFlags.NonPublic); Delegate subscribers = (Delegate)field?.GetValue(null); if (subscribers == null) continue; // 遍历所有订阅者逐一移除 foreach (Delegate d in subscribers.GetInvocationList()) { eventInfo.RemoveEventHandler(null, d); } } }
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

