【问题标题】:Can I have validators inside validators with fluent validation我可以在验证器中使用流利验证的验证器吗
【发布时间】:2018-11-26 10:26:23
【问题描述】:

c#伪代码

如果我有课

class Person
{
  string Name
  date DOB
  Address address
}

我可以制作一个 PersonValidator 来验证 Person

但由于 Address 是一个复杂类型,有时我想单独验证它,我有一个 PersonValidator 和一个 AddressValidator。问题是,如何在 PersonValidator 中使用 AddressValidator?

class PersonValidator : AbstractValidator<Person>
{
   PersonValidator()
   {
       RuleFor(c => c.Name).NotEmpty();

       var addressValidator = new AddressValidator();
       addressValidator.Validate( person.address ) // ???
    }
}

【问题讨论】:

    标签: c# fluentvalidation


    【解决方案1】:

    您可以调用.SetValidator(IValidator) 方法。

    class PersonValidator : AbstractValidator<Person>
    {
       PersonValidator()
       {
           // CascadeMode = CascadeMode.StopOnFirstFailure;
    
           RuleFor(c => c.Name)
               .NotEmpty().WithErrorCode("name_required");
    
           // Checks that the IEnumerable<Address> has at least 1 item
           RuleFor(c => c.Address)
               .NotEmpty().WithErrorCode("addresses_required");
    
           RuleForEach(c => c.Address)
               .SetValidator(new AddressValidator());
    
        }
    }
    
    class AddressValidator : AbstractValidator<Address>
    {
       AddressValidator()
       {
           // CascadeMode = CascadeMode.Continue;
    
           RuleFor(c => c.Postcode)
               .NotEmpty().WithErrorCode("postcode_required");
       }
    }
    

    【讨论】:

    • 我自己也想通了,改变了接受的答案。还有一个被贬低的SetCollectionValidator 我在另一个答案的评论中提到的另一个问题我的地址实际上是一个集合,它说使用RuleForEach(c =&gt; c.Addresses).SetValidator(new AddressValidator());
    • 谢谢。从单元测试 POV 中,还有 _personValidator.ShouldHaveChildValidator(x =&gt; x.Address, typeof(AddressValidator)); 可以满足该用例的需求
    【解决方案2】:

    您可以覆盖验证方法:

    public override ValidationResult Validate(ValidationContext<T> context) {
        var baseResult = base.Validate(context);
        var result = new AddressValidator().Validate(new ValidationContext<Address>(context.InstanceToValidate.Address);
        return new ValidationResult(baseResult.Errors.Concat(result.Errors));
    }
    

    对异步方法变体也这样做。

    【讨论】:

    • 谢谢,这似乎有效。不过,我确实有一个问题,在我的用例中,我意识到地址实际上是一个地址数组。我知道有 RuleForEach 但我不确定是否有办法使用您示例中的代码来处理每个代码,而不是将其放入循环中。有什么想法吗?
    • 从我的头顶我只想让它成为一个循环。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多