FluentValidation多个验证器

Bja*_*ðar 12 .net c# fluentvalidation

我可以为对象添加多个验证器吗?例如:

public interface IFoo
{
    int Id { get; set; }
    string Name { get; set; }
}

public interface IBar
{
    string Stuff { get; set; }
}

public class FooValidator : AbstractValidator<IFoo>
{
    public FooValidator ()
    {
        RuleFor(x => x.Id).NotEmpty().GreaterThan(0);
    }
}

public class BarValidator : AbstractValidator<IBar>
{
    public BarValidator()
    {
        RuleFor(x => x.Stuff).Length(5, 30);
    }
}

public class FooBar : IFoo, IBar
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Stuff { get; set; }
}

public class FooBarValidator : AbstractValidator<FooBar>
{
    public FooBarValidator()
    {
        RuleFor(x => x)
            .SetValidator(new FooValidator())
            .SetValidator(new BarValidator());
    }
}
Run Code Online (Sandbox Code Playgroud)

运行测试.

FooBarValidator validator = new FooBarValidator();
validator.ShouldHaveValidationErrorFor(x => x.Id, 0);
Run Code Online (Sandbox Code Playgroud)

我得到一个InvalidOperationException:

无法为表达式x => x自动确定属性名称.请通过调用'WithName'指定自定义属性名称.

有没有办法实现这个,或者我试图以一种不打算使用的方式使用FluentValidation?

Eli*_*ert 19

RuleFor正在尝试创建属性级规则.您还可以使用AddRule函数添加通用规则.

使用这个,我创建了一个复合规则的概念证明.它接受一组其他验证器并运行它们.该yield break代码开门见山FluentValidatorDelegateValidator.我不知道该怎么办,所以我从源头抓住了它.我没有追溯它的全部目的,但一切似乎都工作:)

public interface IFoo
{
    int Id { get; set; }
    string Name { get; set; }
}

public interface IBar
{
    string Stuff { get; set; }
}

public class FooValidator : AbstractValidator<IFoo>
{
    public FooValidator()
    {
        RuleFor(x => x.Id).NotEmpty().GreaterThan(0);
    }
}

public class BarValidator : AbstractValidator<IBar>
{
    public BarValidator()
    {
        RuleFor(x => x.Stuff).Length(5, 30);
    }
}

public class FooBar : IFoo, IBar
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Stuff { get; set; }
}

public class CompositeValidatorRule : IValidationRule
{
    private IValidator[] _validators;

    public CompositeValidatorRule(params IValidator[] validators)
    {
        _validators = validators;
    }

    #region IValidationRule Members
    public string RuleSet
    {
        get; set;
    }

    public IEnumerable<ServiceStack.FluentValidation.Results.ValidationFailure> Validate(ValidationContext context)
    {
        var ret = new List<ServiceStack.FluentValidation.Results.ValidationFailure>();

        foreach(var v in _validators)
        {
            ret.AddRange(v.Validate(context).Errors);
        }

        return ret;
    }

    public IEnumerable<ServiceStack.FluentValidation.Validators.IPropertyValidator> Validators
    {
        get { yield break; }
    }
    #endregion
}

public class FooBarValidator : AbstractValidator<FooBar>
{
    public FooBarValidator()
    {
        AddRule(new CompositeValidatorRule(new FooValidator(), new BarValidator()));
    }
}
Run Code Online (Sandbox Code Playgroud)

基础测试案例:

    [TestMethod]
    public void TestValidator()
    {
        FooBarValidator validator = new FooBarValidator();
        var result = validator.Validate(new FooBar());

    }
Run Code Online (Sandbox Code Playgroud)

我希望这有帮助.

  • 通过一点反射,您可以自动查找复合验证器应该连接的所有验证器(即查找所有接口和基类链,看看是否有IValidator <T>,如果是这样,自动添加它到列表).只取决于你想要走多远.我可能会选择使用反射来查找所有验证器而不是手动列表. (3认同)

小智 7

“包括规则。您可以包括其他验证器的规则,前提是它们验证相同的类型。”

public class PersonValidator : AbstractValidator<Person> {
    public PersonValidator() {
        Include(new PersonAgeValidator());
        Include(new PersonNameValidator());
    }
}
Run Code Online (Sandbox Code Playgroud)

https://docs.fluidation.net/en/latest/include-rules.html


小智 5

另一种可能性是覆盖验证:

public override ValidationResult Validate(ValidationContext<FooBar> context)
{
    var fooResult = new FooValidator().Validate(context.InstanceToValidate);
    var barResult = new BarValidator().Validate(context.InstanceToValidate);

    var errors = new List<ValidationFailure>();
    errors.AddRange(fooResult.Errors);
    errors.AddRange(barResult.Errors);

    return new ValidationResult(errors);
}
Run Code Online (Sandbox Code Playgroud)