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

如何创建Action<T>列表?实现类型匹配事件中心遇阻求助

实现基于类型匹配的事件中心方案

你的核心问题在于不同泛型参数的Action<T>是完全不同的委托类型,无法直接存入同一个字典——哪怕用dynamic也不行,因为Action<T>和Action<dynamic>的类型系统不兼容。下面给你一个既满足类型安全、调用性能又几乎无损耗的实现方案:

核心思路

用Action<object>作为字典的Value类型,在注册时将泛型Action<T>包装成Action<object>(内部做类型转换),调用时直接传入对象并执行包装后的委托。这种方式注册时仅做一次委托包装,调用时只有一次轻量的类型转换(引用类型无装箱开销,值类型只有一次装箱),完全符合你"调用无较大性能损耗"的要求。

修改后的完整代码

// 字典改用Action<object>作为值类型
private readonly Dictionary<Type, Action<object>> _functions = new Dictionary<Type, Action<object>>();

public void RegisterHandler<T>(Action<T> handler) where T : BaseClass
{
    var type = typeof(T);
    // 可选:避免重复注册同一类型的处理器
    if (_functions.ContainsKey(type))
        throw new InvalidOperationException($"Handler for type {type.Name} is already registered.");
    
    // 将Action<T>包装成Action<object>,内部安全转换类型
    _functions[type] = obj => handler((T)obj);
}

public void CallMethod(BaseClass data)
{
    if (_functions.TryGetValue(data.GetType(), out var handler))
    {
        handler.Invoke(data);
    }
    else
    {
        // 可选:处理未注册类型的情况,比如抛出异常或忽略
        throw new KeyNotFoundException($"No handler registered for type {data.GetType().Name}");
    }
}

为什么这个方案可行?

  1. 类型安全:注册时通过泛型约束where T : BaseClass保证传入的T都是BaseClass的子类,所以包装时的(T)obj转换是安全的(不会出现类型转换失败)。
  2. 性能优异:调用时只是执行一个预先包装好的委托,内部的类型转换是CLR原生支持的操作,性能损耗微乎其微——比反射调用快几个数量级。
  3. 实现简洁:不需要复杂的反射逻辑,注册时的包装代码非常简单,维护成本低。

可选扩展

如果你需要支持子类触发父类的处理器(比如注册了BaseClass的处理器,传入子类实例也能触发),可以在CallMethod中遍历类型的继承链查找处理器,示例如下:

public void CallMethod(BaseClass data)
{
    var type = data.GetType();
    while (type != null && type != typeof(object))
    {
        if (_functions.TryGetValue(type, out var handler))
        {
            handler.Invoke(data);
            // 可选:找到后是否继续查找父类处理器,按需调整
            return;
        }
        type = type.BaseType;
    }
    throw new KeyNotFoundException($"No handler registered for type {data.GetType().Name} or its base types.");
}

内容的提问来源于stack exchange,提问作者Swazimodo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:14:56