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

C#中如何基于输入参数用LINQ查询不同DataSet替代switch case

方案说明

完全可以绕过switch case实现需求,根据项目复杂度和后续扩展需求,可以选择以下两种实现方式:

轻量实现(适合分类少、变动不频繁的场景)

不需要额外定义抽象和独立类,直接在业务类初始化时构建分类与查询委托的映射字典,调用时按传入分类取对应委托执行即可,代码如下:

public class YourBusinessService
{
    private readonly YourDbContext _data;
    private readonly IMapper _mapper;
    private readonly IReadOnlyDictionary<string, Func<int, CancellationToken, Task<RequestOutputModel>>> _queryHandlers;

    // 构造函数注入依赖,同时初始化查询映射字典
    public YourBusinessService(YourDbContext data, IMapper mapper)
    {
        _data = data;
        _mapper = mapper;
        _queryHandlers = new Dictionary<string, Func<int, CancellationToken, Task<RequestOutputModel>>>(StringComparer.OrdinalIgnoreCase)
        {
            ["RequestTypeOne"] = async (id, ct) => await _mapper
                .ProjectTo<RequestTypeOneOutputModel>(_data.RequestTypeOne.Where(e => e.Id == id))
                .FirstOrDefaultAsync(ct),
            ["RequestTypeTwo"] = async (id, ct) => await _mapper
                .ProjectTo<RequestTypeTwoOutputModel>(_data.RequestTypeTwo.Where(e => e.Id == id))
                .FirstOrDefaultAsync(ct)
            // 后续新增分类只需要在这里加一行映射即可
        };
    }

    public async Task<RequestOutputModel> SearchById(int id, string category, CancellationToken cancellationToken)
    {
        if (!_queryHandlers.TryGetValue(category, out var handler))
        {
            // 可替换为项目内自定义的业务异常
            throw new ArgumentException($"不支持的分类类型: {category}", nameof(category));
        }
        return await handler(id, cancellationToken);
    }
}

可扩展实现(适合分类多、后续迭代频繁的场景)

基于策略模式实现,符合开闭原则,后续新增分类不需要修改核心查询逻辑:

  1. 首先定义统一的查询策略接口,约束所有分类查询的标准
/// <summary>
/// 分类查询策略接口
/// </summary>
public interface ICategoryQueryStrategy
{
    /// <summary>
    /// 当前策略支持的分类标识
    /// </summary>
    string CategoryName { get; }
    /// <summary>
    /// 按Id执行查询
    /// </summary>
    Task<RequestOutputModel> QueryByIdAsync(int id, CancellationToken cancellationToken);
}
  1. 为每个分类实现独立的策略类,以RequestTypeOne为例:
public class RequestTypeOneQueryStrategy : ICategoryQueryStrategy
{
    private readonly YourDbContext _data;
    private readonly IMapper _mapper;

    public RequestTypeOneQueryStrategy(YourDbContext data, IMapper mapper)
    {
        _data = data;
        _mapper = mapper;
    }

    public string CategoryName => "RequestTypeOne";

    public async Task<RequestOutputModel> QueryByIdAsync(int id, CancellationToken cancellationToken)
    {
        return await _mapper
            .ProjectTo<RequestTypeOneOutputModel>(_data.RequestTypeOne.Where(e => e.Id == id))
            .FirstOrDefaultAsync(cancellationToken);
    }
}

RequestTypeTwo的实现逻辑与上述一致,仅需替换对应的DbSet和输出模型类型即可。
3. 注册策略与分发器,在服务配置阶段完成所有策略的自动扫描和映射:

// Program.cs 服务注册代码
// 自动扫描程序集中所有策略实现并注册
builder.Services.Scan(scan => scan
    .FromAssemblyOf<ICategoryQueryStrategy>()
    .AddClasses(classes => classes.AssignableTo<ICategoryQueryStrategy>())
    .AsImplementedInterfaces()
    .WithScopedLifetime());

// 注册查询分发器
builder.Services.AddScoped<CategoryQueryDispatcher>(sp =>
{
    var strategies = sp.GetRequiredService<IEnumerable<ICategoryQueryStrategy>>();
    var strategyDict = strategies.ToDictionary(s => s.CategoryName, StringComparer.OrdinalIgnoreCase);
    return new CategoryQueryDispatcher(strategyDict);
});

分发器的核心逻辑很简单,负责根据传入分类匹配对应策略执行:

public class CategoryQueryDispatcher
{
    private readonly IReadOnlyDictionary<string, ICategoryQueryStrategy> _strategyDict;

    public CategoryQueryDispatcher(IReadOnlyDictionary<string, ICategoryQueryStrategy> strategyDict)
    {
        _strategyDict = strategyDict;
    }

    public async Task<RequestOutputModel> SearchById(int id, string category, CancellationToken cancellationToken)
    {
        if (!_strategyDict.TryGetValue(category, out var strategy))
        {
            throw new ArgumentException($"不支持的分类类型: {category}", nameof(category));
        }
        return await strategy.QueryByIdAsync(id, cancellationToken);
    }
}
  1. 最终业务类只需要注入分发器即可直接调用,不需要写任何分支判断:
public class YourBusinessService
{
    private readonly CategoryQueryDispatcher _queryDispatcher;

    public YourBusinessService(CategoryQueryDispatcher queryDispatcher)
    {
        _queryDispatcher = queryDispatcher;
    }

    public Task<RequestOutputModel> SearchById(int id, string category, CancellationToken cancellationToken)
    {
        return _queryDispatcher.SearchById(id, category, cancellationToken);
    }
}

方案优势

  • 所有分支逻辑统一管理,不会出现switch分支过长导致的代码可读性差、维护成本高的问题
  • 轻量实现无额外抽象,开发成本低,适配简单业务场景
  • 策略模式实现下单个分类的查询逻辑独立拆分,职责单一,方便编写单元测试,新增分类时不会侵入原有业务代码
  • 字典匹配默认配置大小写不敏感,避免传参格式问题导致的匹配异常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 20:42:18