C# 如何组织FluentValidation规则,以便它们可以在多个验证器中重用?

C# 如何组织FluentValidation规则,以便它们可以在多个验证器中重用?,c#,fluentvalidation,C#,Fluentvalidation,我有一个域模型/实体,根据它的填充方式,需要进行不同的验证。假设我提出了3个验证器,如下所示: public class Product1Validator : AbstractValidator<Ticket> { public Product1Validator() { RuleFor(ticket => ticket.Policy.PolicyNumber) .NotEmpty() .WithMessag

我有一个域模型/实体,根据它的填充方式,需要进行不同的验证。假设我提出了3个验证器,如下所示:

public class Product1Validator : AbstractValidator<Ticket>
{
    public Product1Validator()
    {
        RuleFor(ticket => ticket.Policy.PolicyNumber)
         .NotEmpty()
         .WithMessage("Policy Number is missing.");

        RuleFor(ticket => ticket.Policy.ApplSignedInState)
         .NotEmpty()
         .WithMessage("Application Signed In State is missing or invalid.");
    }
}

public class Product2Validator : AbstractValidator<Ticket>
{
    public Product2Validator()
    {
        RuleFor(ticket => ticket.Policy.PolicyNumber)
         .NotEmpty()
         .WithMessage("Policy Number is missing.");

        RuleFor(ticket => ticket.Policy.ApplSignedInState)
         .NotEmpty()
         .WithMessage("Application Signed In State is missing or invalid.");
    }
}


public class Product3Validator : AbstractValidator<Ticket>
{
    public Product3Validator()
    {
        RuleFor(ticket => ticket.Policy.PolicyNumber)
         .NotEmpty()
         .WithMessage("Policy Number is missing.");

        RuleFor(ticket => ticket.Policy.ApplSignedInState)
         .NotEmpty()
         .WithMessage("Application Signed In State is missing or invalid.");

        RuleFor(ticket => ticket.Policy.DistributionChannel)
         .NotEmpty()
         .WithMessage("Distribution Channel is missing."); 
    }
}
更新2

问题是新的复合验证器没有继承自AbstractValidator,一旦我纠正了这个问题,它就会编译,但它们似乎不起作用

public class Product1Validator : AbstractValidator<Ticket>
{
    public Product1Validator()
    {
        TicketValidator.Validate().Policy().ApplSignedState();
    }
} 
公共类Product1Validator:AbstractValidator
{
公共产品1validator()
{
TicketValidator.Validate().Policy().ApplSignedState();
}
} 
更新3

在对最初的答案大发雷霆并直接在GitHub上联系Jeremy后,我想到了以下几点:

class Program{
    static void Main(string[] args){
        var p = new Person();
        var pv = new PersonValidator();
        var vr = pv.Validate(p);
        //Console.ReadKey();
    }
}

class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime BirthDate { get; set; }
}

class PersonValidator : AbstractValidator<Person>
{
    public PersonValidator()
    {
        CascadeMode = CascadeMode.Continue;
        this.FirstName();
        this.LastName();
    }
}

static class Extensions
{
    public static void FirstName(this AbstractValidator<Person> a)
    {
        a.RuleFor(b => b.FirstName).NotEmpty();
    }
    public static void LastName(this AbstractValidator<Person> a)
    {
        a.RuleFor(b => b.LastName).NotEmpty();
    }
}
类程序{
静态void Main(字符串[]参数){
var p=新人();
var pv=新的PersonValidator();
var vr=pv.Validate(p);
//Console.ReadKey();
}
}
班主任
{
公共字符串名{get;set;}
公共字符串LastName{get;set;}
公共日期时间出生日期{get;set;}
}
类PersonValidator:AbstractValidator
{
公共PersonValidator()
{
级联模式=级联模式。继续;
this.FirstName();
this.LastName();
}
}
静态类扩展
{
公共静态void FirstName(此抽象验证器a)
{
a、 RuleFor(b=>b.FirstName).NotEmpty();
}
公共静态void LastName(此抽象验证器a)
{
a、 RuleFor(b=>b.LastName).NotEmpty();
}
}

在您的情况下,我可能会尝试使用所有规则为票据建立一个流畅的验证,然后调用每个产品所需的验证。比如:

public class TicketValidator : AbstractValidator<Ticket>
{
    public TicketValidator Policy()
    {
        RuleFor(ticket => ticket.Policy.PolicyNumber)
         .NotEmpty()
         .WithMessage("Policy Number is missing.");

        return this;
    }

    public TicketValidator ApplSignedState()
    {
        RuleFor(ticket => ticket.Policy.ApplSignedInState)
         .NotEmpty()
         .WithMessage("Application Signed In State is missing or invalid.");

        return this;
    }

    public TicketValidator DistributionChannel()
    {
        RuleFor(ticket => ticket.Policy.DistributionChannel)
        .NotEmpty()
        .WithMessage("Distribution Channel is missing.");

        return this;
    }

    public static TicketValidator Validate()
    {
        return new TicketValidator();
    }
}
我没有试图编译这段代码,但我希望你能看到这个想法


希望有帮助。

集中扩展方法方法

我想跨多种不同类型的对象使用它们

我通过创建集中的扩展方法实现了这一点

一个简单的例子:

扩展方法

namespace FluentValidation
{
    public static class LengthValidator
    {
        public static IRuleBuilderOptions<T, string> 
           CustomerIdLength<T>(this IRuleBuilder<T, string> ruleBuilder)
        {
            return ruleBuilder.Length<T>(1, 0);
        }
    }
}
名称空间FluentValidation
{
公共静态类长度验证器
{
公共静态IRuleBuilderOptions
CustomerIdLength(此IRuleBuilder规则生成器)
{
返回ruleBuilder.Length(1,0);
}
}
}
用法

public class CreateCustomerValidator : AbstractValidator<CreateCustomerCommand>
{
    public CreateCustomerValidator()
    {
        RuleFor(x => x.CustomerId).CustomerIdLength();
    }
}
公共类CreateCustomerValidator:AbstractValidator
{
public CreateCustomerValidator()
{
(x=>x.CustomerId).CustomerIdLength()的规则;
}
}
当类型化对象通过泛型传递时,它可以跨多个对象使用,而不仅仅是一个对象


公共类UpdateCustomerValidator:AbstractValidator

原样编译的代码很好,谢谢。但是当我编写代码调用它时,它不会编译。正如您在我的代码中看到的,验证函数必须由您编写,在我的示例中,它只是一个返回空验证器的工厂方法。如果你愿意,可以叫它Empty()或Build()或Create(),对不起,我有点笨。你是说要修改“publicstaticticketvalidator validator()”,我不太明白你的意思。我确实喜欢链子的样子,但我不能让它工作。
namespace FluentValidation
{
    public static class LengthValidator
    {
        public static IRuleBuilderOptions<T, string> 
           CustomerIdLength<T>(this IRuleBuilder<T, string> ruleBuilder)
        {
            return ruleBuilder.Length<T>(1, 0);
        }
    }
}
public class CreateCustomerValidator : AbstractValidator<CreateCustomerCommand>
{
    public CreateCustomerValidator()
    {
        RuleFor(x => x.CustomerId).CustomerIdLength();
    }
}