You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过反射清空类中所有静态事件的已注册处理程序?

解决方案

方法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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 09:27:01