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

C#中如何强制字典的Type键属于特定继承层级?

解决方案

首先先明确基础类型定义,比如先定义所有Command的基类,以及泛型约束的命令处理器基类:

// 所有Command的共同基类
public abstract class BaseCommand { }

// 命令处理器的泛型基类,强制绑定继承自BaseCommand的命令
public abstract class TypeHandler<TCommand> where TCommand : BaseCommand
{
    // 处理器核心逻辑方法示例
    public abstract void Handle(TCommand command);
}

直接用Dictionary<Type, TypeHandler>无法在编译阶段约束Key的类型,因此最稳妥的方式是封装一个自定义的强类型字典类,通过泛型方法实现编译时类型校验:

public class CommandHandlerDictionary
{
    private readonly Dictionary<Type, object> _innerDict = new Dictionary<Type, object>();

    // 泛型Add方法,强制约束TCommand必须继承自BaseCommand
    public void Add<TCommand>(TypeHandler<TCommand> handler) where TCommand : BaseCommand
    {
        var commandType = typeof(TCommand);
        if (_innerDict.ContainsKey(commandType))
        {
            throw new InvalidOperationException($"已存在针对{commandType.Name}的处理器");
        }
        _innerDict.Add(commandType, handler);
    }

    // 泛型获取方法,保证返回对应命令的处理器
    public TypeHandler<TCommand> GetHandler<TCommand>() where TCommand : BaseCommand
    {
        var commandType = typeof(TCommand);
        if (_innerDict.TryGetValue(commandType, out var handler))
        {
            return handler as TypeHandler<TCommand>;
        }
        throw new KeyNotFoundException($"未找到针对{commandType.Name}的处理器");
    }
}

使用示例

// 定义具体命令(必须继承BaseCommand)
public class CreateOrderCommand : BaseCommand
{
    public string OrderId { get; set; }
}

// 对应命令的处理器
public class CreateOrderHandler : TypeHandler<CreateOrderCommand>
{
    public override void Handle(CreateOrderCommand command)
    {
        Console.WriteLine($"处理订单创建:{command.OrderId}");
    }
}

// 初始化并使用字典
var handlerDict = new CommandHandlerDictionary();
handlerDict.Add(new CreateOrderHandler()); // 合法,符合继承约束

// 错误示例:如果命令未继承BaseCommand,编译阶段直接报错
// public class InvalidCommand { }
// public class InvalidHandler : TypeHandler<InvalidCommand> { }
// handlerDict.Add(new InvalidHandler()); // 编译失败,不符合泛型约束

如果不想封装自定义类,也可以通过封装添加方法做运行时校验(但仅能在运行时发现错误,不如编译时约束可靠):

var dic = new Dictionary<Type, TypeHandler>();

public void AddValidHandler<TCommand>(TypeHandler handler) where TCommand : BaseCommand
{
    var commandType = typeof(TCommand);
    if (!typeof(BaseCommand).IsAssignableFrom(commandType))
    {
        throw new ArgumentException($"类型{commandType.Name}必须继承自BaseCommand");
    }
    dic.Add(commandType, handler);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 02:31:04