如何将C# API请求属性验证类改造为泛型实现?
泛化请求验证类的解决方案
我来帮你搞定这个泛型改造的问题!核心思路就是把原来硬编码的UserSearchRequest替换成泛型参数,同时确保泛型类能适配你所有的请求对象类型。下面是具体的改造步骤和代码示例:
1. 改造验证类为泛型
首先,把你的验证类改成泛型版本,给泛型参数添加合适的约束(确保可以被反序列化和实例化):
using Newtonsoft.Json; using System.ComponentModel.DataAnnotations; using System.Collections.Generic; public class RequestValidator<T> where T : class, new() { // 验证请求JSON是否包含无效属性/不符合规则的内容 public bool ContainsInvalidProperties(string requestJson) { try { // 反序列化为泛型类型T var requestModel = JsonConvert.DeserializeObject<T>(requestJson); // 这里用数据注解做通用验证,你可以替换成自己的原有验证逻辑 var validationResults = new List<ValidationResult>(); var validationContext = new ValidationContext(requestModel); // 验证所有属性(包括标注了[Required]、[MaxLength]等的属性) var isValid = Validator.TryValidateObject( requestModel, validationContext, validationResults, validateAllProperties: true); // 如果验证不通过,说明存在无效属性 return !isValid; } catch (JsonSerializationException) { // 反序列化失败,说明JSON里有模型不存在的属性或格式错误 return true; } } }
关键说明:
where T : class, new():约束T必须是引用类型,且有无参构造函数,这是JsonConvert.DeserializeObject<T>的基本要求。- 把原来的
DeserializeObject<UserSearchRequest>改成DeserializeObject<T>,实现类型的动态适配。 - 这里用了.NET自带的
Validator和数据注解做通用验证,如果你的原有逻辑是自定义的,直接替换成泛型版本即可(比如把原来针对UserSearchRequest的属性检查改成遍历T的属性)。
2. 泛型类的使用示例
现在你可以用这个泛型类验证任意请求类型了:
// 验证UserSearchRequest var userValidator = new RequestValidator<UserSearchRequest>(); bool hasInvalidUserProps = userValidator.ContainsInvalidProperties(userSearchJsonString); // 验证GroupSearchRequest var groupValidator = new RequestValidator<GroupSearchRequest>(); bool hasInvalidGroupProps = groupValidator.ContainsInvalidProperties(groupSearchJsonString); // 验证XSearchRequest同理 var xValidator = new RequestValidator<XSearchRequest>(); bool hasInvalidXProps = xValidator.ContainsInvalidProperties(xSearchJsonString);
3. 处理自定义验证逻辑(可选)
如果不同的请求类型有特殊的验证规则,你可以给泛型方法加一个自定义验证委托,让类更灵活:
public bool ContainsInvalidProperties( string requestJson, Func<T, bool> customValidation = null) { try { var requestModel = JsonConvert.DeserializeObject<T>(requestJson); // 基础数据注解验证 var validationResults = new List<ValidationResult>(); var validationContext = new ValidationContext(requestModel); var baseIsValid = Validator.TryValidateObject( requestModel, validationContext, validationResults, validateAllProperties: true); // 如果有自定义验证,结合基础验证结果 if (customValidation != null) { return !baseIsValid || !customValidation(requestModel); } return !baseIsValid; } catch (JsonSerializationException) { return true; } }
使用时传入自定义规则:
// 给UserSearchRequest加额外验证:检查UserName不能是admin bool hasInvalid = userValidator.ContainsInvalidProperties( userSearchJsonString, model => model.UserName != "admin");
4. 关于你提到的BindM...方法问题
如果你是在模型绑定(比如ASP.NET Core的BindModelAsync)中使用泛型,只需要确保在绑定器中指定泛型参数,或者通过泛型工厂来创建实例。举个自定义模型绑定器的例子:
public class GenericRequestBinder<T> : IModelBinder where T : class, new() { public async Task BindModelAsync(ModelBindingContext bindingContext) { var requestBody = await new StreamReader(bindingContext.HttpContext.Request.Body).ReadToEndAsync(); var validator = new RequestValidator<T>(); if (validator.ContainsInvalidProperties(requestBody)) { bindingContext.ModelState.AddModelError(string.Empty, "请求包含无效属性或不符合规则的内容"); return; } var model = JsonConvert.DeserializeObject<T>(requestBody); bindingContext.Result = ModelBindingResult.Success(model); } }
然后在模型上标注:
[ModelBinder(typeof(GenericRequestBinder<UserSearchRequest>))] public class UserSearchRequest { // 属性... }
这样就能在模型绑定时自动完成验证啦!
内容的提问来源于stack exchange,提问作者user9393635
相关产品推荐
相关产品推荐

