C# 可在fluent验证中重用的自定义验证器
我希望在不重复验证相同属性的情况下实现流畅的验证。正在寻找一种可以重用验证的方法 我有如下三个类,Customer和NewClass都是相同的,只是NewClass继承了PageRequestC# 可在fluent验证中重用的自定义验证器,c#,fluentvalidation,C#,Fluentvalidation,我希望在不重复验证相同属性的情况下实现流畅的验证。正在寻找一种可以重用验证的方法 我有如下三个类,Customer和NewClass都是相同的,只是NewClass继承了PageRequest public sealed class Customer { public int Id{get; set;} public string FirstName {get; set;} public string LastName {get; set;} public string MiddleName
public sealed class Customer {
public int Id{get; set;}
public string FirstName {get; set;}
public string LastName {get; set;}
public string MiddleName {get; set;}
public string Address {get; set;}
}
public class PageRequest
{
public int CurrentPage {get; set;}
public int PerPage {get; set;}
public string SortBy {get; set;}
}
public class NewClass : PageRequest
{
public int Id{get; set;}
public string FirstName {get; set;}
public string LastName {get; set;}
public string MiddleName {get; set;}
public string Address {get; set;}
}
Fluent验证如下所示:
public abstract class GetPaginatedDataRequestValidator<TRequest, TModel> : AbstractValidator<TRequest>
where TRequest : PageRequest
{
protected GetPaginatedDataRequestValidator()
{
var properties = typeof(TModel).GetProperties().Select(x => x.Name).ToList();
RuleFor(x => x.CurrentPage).Required().GreaterThan(0);
RuleFor(x => x.PerPage).Required().GreaterThan(0);
RuleFor(x => x.SortBy)
.Must(x => properties.Contains(x, StringComparer.OrdinalIgnoreCase))
.When(x => !string.IsNullOrEmpty(x.SortBy))
.WithMessage("{PropertyName} must be a known property name of a " + typeof(TModel).Name.Humanize());
}
}
public class NewClassValidator : GetPaginatedDataRequestValidator<
NewClass, SomeDto>
{
public NewClassValidator()
{
const string message = "At least one of either first name, last name, address and postcode are required.";
RuleFor(x => x.FirstName)
.Required()
.When(x => string.IsNullOrEmpty(x.LastName)
&& string.IsNullOrEmpty(x.Address) && string.IsNullOrEmpty(x.PostCode))
.WithMessage(message);
RuleFor(x => x.LastName)
.Required()
.When(x => string.IsNullOrEmpty(x.FirstName)
&& string.IsNullOrEmpty(x.Address) && string.IsNullOrEmpty(x.PostCode))
.WithMessage(message);
RuleFor(x => x.Address)
.Required()
.When(x => string.IsNullOrEmpty(x.LastName)
&& string.IsNullOrEmpty(x.FirstName) && string.IsNullOrEmpty(x.PostCode))
.WithMessage(message);
RuleFor(x => x.PostCode)
.Required()
.When(x => string.IsNullOrEmpty(x.LastName)
&& string.IsNullOrEmpty(x.Address) && string.IsNullOrEmpty(x.FirstName))
.WithMessage(message);
}
}
public class CustomerValidator : AbstractValidator<Customer>
{
public CustomerValidator()
{
const string message = "At least one of either first name, last name, address and postcode are required.";
RuleFor(x => x.FirstName)
.Required()
.When(x => string.IsNullOrEmpty(x.LastName)
&& string.IsNullOrEmpty(x.Address) && string.IsNullOrEmpty(x.PostCode))
.WithMessage(message);
RuleFor(x => x.LastName)
.Required()
.When(x => string.IsNullOrEmpty(x.FirstName)
&& string.IsNullOrEmpty(x.Address) && string.IsNullOrEmpty(x.PostCode))
.WithMessage(message);
RuleFor(x => x.Address)
.Required()
.When(x => string.IsNullOrEmpty(x.LastName)
&& string.IsNullOrEmpty(x.FirstName) && string.IsNullOrEmpty(x.PostCode))
.WithMessage(message);
RuleFor(x => x.PostCode)
.Required()
.When(x => string.IsNullOrEmpty(x.LastName)
&& string.IsNullOrEmpty(x.Address) && string.IsNullOrEmpty(x.FirstName))
.WithMessage(message);
}
}
公共抽象类GetPaginatedDataRequestValidator:AbstractValidator
其中TRequest:PageRequest
{
受保护的GetPaginatedDataRequestValidator()
{
var properties=typeof(TModel).GetProperties().Select(x=>x.Name).ToList();
(x=>x.CurrentPage).Required()的规则大于(0);
RuleFor(x=>x.PerPage).Required().greaterth(0);
规则(x=>x.SortBy)
.Must(x=>properties.Contains(x,StringComparer.OrdinalIgnoreCase))
.When(x=>!string.IsNullOrEmpty(x.SortBy))
.WithMessage(“{PropertyName}必须是“+typeof(TModel).name.Humanize())的已知属性名);
}
}
公共类NewClassValidator:GetPaginatedDataRequestValidator<
新建类,有些要>
{
公共NewClassValidator()
{
const string message=“至少需要名字、姓氏、地址和邮政编码中的一个。”;
RuleFor(x=>x.FirstName)
.Required()
.When(x=>string.IsNullOrEmpty(x.LastName)
&&string.IsNullOrEmpty(x.Address)和&string.IsNullOrEmpty(x.PostCode))
.WithMessage(消息);
RuleFor(x=>x.LastName)
.Required()
.When(x=>string.IsNullOrEmpty(x.FirstName)
&&string.IsNullOrEmpty(x.Address)和&string.IsNullOrEmpty(x.PostCode))
.WithMessage(消息);
规则(x=>x.Address)
.Required()
.When(x=>string.IsNullOrEmpty(x.LastName)
&&string.IsNullOrEmpty(x.FirstName)和&string.IsNullOrEmpty(x.PostCode))
.WithMessage(消息);
规则(x=>x.邮政编码)
.Required()
.When(x=>string.IsNullOrEmpty(x.LastName)
&&string.IsNullOrEmpty(x.Address)和&string.IsNullOrEmpty(x.FirstName))
.WithMessage(消息);
}
}
公共类CustomerValidator:AbstractValidator
{
公共CustomerValidator()
{
const string message=“至少需要名字、姓氏、地址和邮政编码中的一个。”;
RuleFor(x=>x.FirstName)
.Required()
.When(x=>string.IsNullOrEmpty(x.LastName)
&&string.IsNullOrEmpty(x.Address)和&string.IsNullOrEmpty(x.PostCode))
.WithMessage(消息);
RuleFor(x=>x.LastName)
.Required()
.When(x=>string.IsNullOrEmpty(x.FirstName)
&&string.IsNullOrEmpty(x.Address)和&string.IsNullOrEmpty(x.PostCode))
.WithMessage(消息);
规则(x=>x.Address)
.Required()
.When(x=>string.IsNullOrEmpty(x.LastName)
&&string.IsNullOrEmpty(x.FirstName)和&string.IsNullOrEmpty(x.PostCode))
.WithMessage(消息);
规则(x=>x.邮政编码)
.Required()
.When(x=>string.IsNullOrEmpty(x.LastName)
&&string.IsNullOrEmpty(x.Address)和&string.IsNullOrEmpty(x.FirstName))
.WithMessage(消息);
}
}
您可以在customer和newclass验证器中看到相同的属性验证。
我是否可以创建自定义验证器并在Customer和NewClass验证器中重用?
重复属性时是否需要修改类结构?
非常感谢您的帮助您可以通过接口(ICCustomer或类似工具)统一Customer和NewClass类,为接口编写一个验证器,然后在Customer/NewClass验证器中编写该验证器 编辑:MVP LINQPad样本
void Main()
{
var customerValidator = new CustomerValidator();
var customer1 = new Customer();
var customerResult1 = customerValidator.Validate(customer1);
Console.WriteLine(customerResult1.Errors.Select(x => x.ErrorMessage));
var newClassValidator = new NewClassValidator();
var newClass1 = new NewClass { CurrentPage = -1, PerPage = -1, SortBy = "Foo" };
var newClassResult1 = newClassValidator.Validate(newClass1);
Console.WriteLine(newClassResult1.Errors.Select(x => x.ErrorMessage));
}
public interface ICustomer
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string MiddleName { get; set; }
public string Address { get; set; }
public string PostCode { get; set; }
}
public sealed class Customer : ICustomer
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string MiddleName { get; set; }
public string Address { get; set; }
public string PostCode { get; set; }
}
public class PageRequest
{
public int CurrentPage { get; set; }
public int PerPage { get; set; }
public string SortBy { get; set; }
}
public class NewClass : PageRequest, ICustomer
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string MiddleName { get; set; }
public string Address { get; set; }
public string PostCode { get; set; }
}
public class SomeDto
{
}
public class ICustomerValidator : AbstractValidator<ICustomer>
{
public ICustomerValidator()
{
const string message = "At least one of either first name, last name, address and postcode are required.";
RuleFor(x => x.FirstName)
.NotEmpty()
.When(x => string.IsNullOrEmpty(x.LastName) && string.IsNullOrEmpty(x.Address) && string.IsNullOrEmpty(x.PostCode))
.WithMessage(message);
RuleFor(x => x.LastName)
.NotEmpty()
.When(x => string.IsNullOrEmpty(x.FirstName) && string.IsNullOrEmpty(x.Address) && string.IsNullOrEmpty(x.PostCode))
.WithMessage(message);
RuleFor(x => x.Address)
.NotEmpty()
.When(x => string.IsNullOrEmpty(x.LastName) && string.IsNullOrEmpty(x.FirstName) && string.IsNullOrEmpty(x.PostCode))
.WithMessage(message);
RuleFor(x => x.PostCode)
.NotEmpty()
.When(x => string.IsNullOrEmpty(x.LastName) && string.IsNullOrEmpty(x.Address) && string.IsNullOrEmpty(x.FirstName))
.WithMessage(message);
}
}
public class CustomerValidator : AbstractValidator<Customer>
{
public CustomerValidator()
{
Include(new ICustomerValidator());
}
}
public abstract class GetPaginatedDataRequestValidator<TRequest, TModel> : AbstractValidator<TRequest> where TRequest : PageRequest
{
protected GetPaginatedDataRequestValidator()
{
var properties = typeof(TModel).GetProperties().Select(x => x.Name).ToList();
RuleFor(x => x.CurrentPage).GreaterThan(0);
RuleFor(x => x.PerPage).GreaterThan(0);
RuleFor(x => x.SortBy)
.Must(x => properties.Contains(x, StringComparer.OrdinalIgnoreCase))
.When(x => !string.IsNullOrEmpty(x.SortBy))
//.WithMessage("{PropertyName} must be a known property name of a " + typeof(TModel).Name.Humanize());
.WithMessage("{PropertyName} must be a known property name of a " + typeof(TModel).Name);
}
}
public class NewClassValidator : GetPaginatedDataRequestValidator<NewClass, SomeDto>
{
public NewClassValidator()
{
Include(new ICustomerValidator());
}
}
void Main()
{
var customerValidator=新customerValidator();
var customer1=新客户();
var customerResult1=customerValidator.Validate(customer1);
Console.WriteLine(customerResult1.Errors.Select(x=>x.ErrorMessage));
var newClassValidator=newnewclassvalidator();
var newClass1=newnewclass{CurrentPage=-1,PerPage=-1,SortBy=“Foo”};
var newClassResult1=newClassValidator.Validate(newClass1);
WriteLine(newClassResult1.Errors.Select(x=>x.ErrorMessage));
}
公共接口ICustomer
{
公共int Id{get;set;}
公共字符串名{get;set;}
公共字符串LastName{get;set;}
公共字符串MiddleName{get;set;}
公共字符串地址{get;set;}
公共字符串邮政编码{get;set;}
}
公共密封类客户:ICustomer
{
公共int Id{get;set;}
公共字符串名{get;set;}
公共字符串LastName{get;set;}
公共字符串MiddleName{get;set;}
公共字符串地址{get;set;}
公共字符串邮政编码{get;set;}
}
公共类页面请求
{
public int CurrentPage{get;set;}
公共整型每页{get;set;}
公共字符串排序方式{get;set;}
}
公共类NewClass:PageRequest,ICustomer
{
公共int Id{get;set;}
公共字符串名{get;set;}
公共字符串LastName{get;set;}
公共字符串MiddleName{get;set;}
公共字符串地址{get;set;}
公共字符串邮政编码{get;set;}
}
公共课
{
}
公共类ICCustomerValidator:AbstractValidator
{
公共ICustomerValidator()
{
const string message=“名字、姓氏和,