我发明并发现将一些过滤器组合成一种类型(例如 CommonFilters)很有用,并使这种类型可从字符串中解析:
[TypeConverter(typeof(CommonFiltersTypeConverter))]
public class CommonFilters
{
public PageOptions PageOptions { get; set; }
public Range<decimal> Amount { get; set; }
//... other filters
[JsonIgnore]
public bool HasAny => Amount.HasValue || PageOptions!=null;
public static bool TryParse(string str, out CommonFilters result)
{
result = new CommonFilters();
if (string.IsNullOrEmpty(str))
return false;
var parts = str.Split(new[] { ' ', ';' }, StringSplitOptions.RemoveEmptyEntries);
foreach (var part in parts)
{
if (part.StartsWith("amount:") && Range<decimal>.TryParse(part.Substring(7), out Range<decimal> amount))
{
result.Amount = amount;
continue;
}
if (part.StartsWith("page-options:") && PageOptions.TryParse(part.Substring(13), out PageOptions pageOptions))
{
result.PageOptions = pageOptions;
continue;
}
//etc.
}
return result.HasAny;
}
public static implicit operator CommonFilters(string str)
{
if (TryParse(str, out CommonFilters res))
return res;
return null;
}
}
public class CommonFiltersTypeConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string))
{
return true;
}
return base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(ITypeDescriptorContext context,
CultureInfo culture, object value)
{
if (value is string str)
{
if (CommonFilters.TryParse(str, out CommonFilters obj))
{
return obj;
}
}
return base.ConvertFrom(context, culture, value);
}
}
请求如下所示:
public class GetOrdersRequest
{
[DefaultValue("page-options:50;amount:0.001-1000;min-qty:10")]
public CommonFilters Filters { get; set; }
//...other stuff
}
这样可以减少输入请求参数的数量,尤其是当某些查询不关心所有过滤器时
如果你使用 swagger map 这个类型作为字符串:
c.MapTypeAsString<CommonFilters>();
public static void MapTypeAsString<T>(this SwaggerGenOptions swaggerGenOptions)
{
swaggerGenOptions.MapType(typeof(T), () => new OpenApiSchema(){Type = "string"});
}