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

C#如何规范实现请求与实体的匹配过滤逻辑

当前实现的问题

现有写法主要存在两个不规范的点:

  • 职责越界:Gym作为数据/领域实体,不应该感知应用层的GetGymRequest请求结构,IsAppreciateToRequest这类和业务查询强绑定的逻辑放在实体类里,会导致领域层和应用层耦合,后续实体复用、请求结构变更时维护成本极高
  • 逻辑零散:过滤规则没有统一的抽象层,要么散落在Manager方法里堆冗长判断,要么散落在各个实体类里,无法复用,每次新增查询接口都要重复写类似的条件判断,冗余严重
标准重构实现

核心思路是用规约模式统一封装所有过滤规则,把过滤逻辑从实体类、Manager层抽离到独立的规约层,各层职责清晰边界明确。

1. 定义通用规约抽象

先定义所有过滤规则统一实现的接口,强制约束规约的输出形式:

// 通用规约接口,所有实体的过滤规则都实现该接口
public interface ISpecification<T>
{
    Expression<Func<T, bool>> FilterCondition { get; }
}

2. 针对查询场景实现具体规约

把原来写在IsAppreciateToRequest里的判断逻辑,挪到专门针对Gym查询的规约类中,后续所有Gym相关的过滤规则都只在这个类里维护:

public class GymQuerySpecification : ISpecification<Gym>
{
    private readonly GetGymRequest _request;

    public GymQuerySpecification(GetGymRequest request)
    {
        _request = request;
    }

    public Expression<Func<Gym, bool>> FilterCondition
    {
        get
        {
            return gym => 
                (string.IsNullOrEmpty(_request.Name) || gym.Name == _request.Name)
                && (string.IsNullOrEmpty(_request.Location) || gym.Location == _request.Location)
                && (_request.SectionRequest == null || gym.Sections.All(section => 
                    // Section维度的过滤逻辑直接在这里维护,不需要给Section实体也加请求耦合的判断方法
                    (string.IsNullOrEmpty(_request.SectionRequest.Name) || section.Name == _request.SectionRequest.Name)
                    && (!_request.SectionRequest.MinCapacity.HasValue || section.Capacity >= _request.SectionRequest.MinCapacity.Value)
                ));
        }
    }
}

3. 改造仓储层适配规约

给Repository的Find方法增加规约入参的重载,统一处理查询执行逻辑:

public IEnumerable<Gym> Find(ISpecification<Gym> specification)
{
    return _dbContext.Gyms
        .Where(specification.FilterCondition)
        .ToList();
}

4. 简化Manager层逻辑

Manager层不再承载任何过滤判断逻辑,只做流程编排:接收请求、组装对应规约、调用仓储、转换DTO返回,代码结构固定,不会再出现几十行冗余过滤代码的情况:

public IEnumerable<GymDto> GetGyms(GetGymRequest request)
{
    var querySpec = new GymQuerySpecification(request);
    return _gymRepository
           .Find(querySpec)
           .Select(GymDto.FromEntityToDto);
}
重构收益
  • 职责边界清晰:领域实体不再依赖上层请求DTO,Manager层只做流程编排,过滤逻辑统一收敛在规约层
  • 代码复用性高:相同过滤规则的规约可以在不同业务场景直接复用,不需要重复写条件判断
  • 维护成本低:后续调整过滤规则只需要修改对应规约类,不需要翻找Manager或者实体类的零散代码,也不会出现改漏逻辑的问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 02:45:59