You need to enable JavaScript to run this app. 如何设计C#类构造符合限制规则的API请求筛选参数
优惠活动
大模型
产品
解决方案
定价
更多

如何设计C#类构造符合限制规则的API请求筛选参数

实现思路

采用强类型+编译期约束的方案,完全避免硬编码字符串,同时只暴露你需要开放的筛选器,从语法层面限制非法输入。

第一步:定义基础结构

首先定义最终要序列化的Filter结构,以及筛选器的抽象基类,封装通用逻辑:

// 最终要序列化发送给API的Filter结构
public class Filter
{
    public string FilterName { get; set; }
    public string Operator { get; set; }
    public List<string> Values { get; set; } = new();
}

// 筛选器抽象基类,封装通用属性和构建逻辑
public abstract class FilterDefinition
{
    internal abstract string FilterName { get; }
    internal string? Operator { get; set; }
    internal List<string> Values { get; } = new();

    public Filter Build() => new()
    {
        FilterName = FilterName,
        Operator = Operator ?? throw new InvalidOperationException("未设置筛选运算符"),
        Values = Values
    };
}

第二步:实现开放的筛选器

对你需要暴露的少数筛选器单独实现,每个筛选器只开放自身支持的运算符,从接口层面限制非法输入:

// 城市筛选器,支持is/contains
public class CityFilter : FilterDefinition
{
    internal override string FilterName => "City";
    // 仅允许传入该枚举值,编译期自动拦截非法运算符
    public enum AllowedOperators
    {
        Is,
        Contains
    }

    public CityFilter AddOperator(AllowedOperators op)
    {
        Operator = op.ToString().ToLower();
        return this;
    }

    public CityFilter AddValue(string cityName)
    {
        Values.Add(cityName);
        return this;
    }
}

// 州筛选器,仅支持is
public class StateFilter : FilterDefinition
{
    internal override string FilterName => "state";
    public enum AllowedOperators
    {
        Is
    }

    public StateFilter AddOperator(AllowedOperators op)
    {
        Operator = op.ToString().ToLower();
        return this;
    }

    public StateFilter AddValue(string state)
    {
        Values.Add(state);
        return this;
    }
}

// 街道号筛选器,支持range/is/contains
public class StreetNumberFilter : FilterDefinition
{
    internal override string FilterName => "streetNumber";
    public enum AllowedOperators
    {
        Range,
        Is,
        Contains
    }

    public StreetNumberFilter AddOperator(AllowedOperators op)
    {
        Operator = op.ToString().ToLower();
        return this;
    }

    public StreetNumberFilter AddValue(string number)
    {
        Values.Add(number);
        return this;
    }
}

如果你更偏好字符串入参,可以把AddOperator的参数改为字符串,内部增加合法值校验,运行时抛出异常提示即可,不用枚举的话写法更贴近你给出的预期调用示例。

第三步:实现构造器入口

封装构造逻辑,仅允许传入你定义过的合法筛选器:

// 筛选数组构造器
public class FilterArrayBuilder
{
    private readonly List<Filter> _filters = new();

    public FilterArrayBuilder AddFilter(FilterDefinition filterDef)
    {
        _filters.Add(filterDef.Build());
        return this;
    }

    public List<Filter> Build() => _filters.ToList();
}

// 静态入口类,简化调用
public static class FilterBuilder
{
    public static FilterArrayBuilder FilterArray() => new();
    public static CityFilter Cities() => new();
    public static StateFilter State() => new();
    public static StreetNumberFilter StreetNumber() => new();
}

调用示例

完全强类型,编码时会有智能提示,非法输入直接编译报错:

var filters = FilterBuilder.FilterArray()
    .AddFilter(FilterBuilder.Cities()
        .AddOperator(CityFilter.AllowedOperators.Contains)
        .AddValue("杭州"))
    .AddFilter(FilterBuilder.State()
        .AddOperator(StateFilter.AllowedOperators.Is)
        .AddValue("浙江省"))
    .Build();

// 序列化filters即可得到符合要求的JSON请求参数

方案优势

  • 编译期校验:非法的筛选器、运算符直接在编码阶段报错,无需等到运行时调用接口才发现问题
  • 按需开放:API提供的100种筛选器不需要全部实现,只需要实现业务用到的少数几种即可
  • 可维护性强:新增筛选器只需新增对应类,修改规则只需要调整对应筛选器的允许枚举即可,无需改动全局逻辑
  • 无魔法字符串:所有筛选名、运算符都由代码封装,不会出现拼写错误

内容的提问来源于stack exchange,提问作者Mb...R

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.09 03:09:04