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());
    }
}

запуск теста.

FooBarValidator validator = new FooBarValidator();
validator.ShouldHaveValidationErrorFor(x => x.Id, 0);

Я InvalidOperationException:

имя свойства не может быть автоматически определено для выражения x => x. Пожалуйста, укажите имя настраиваемого свойства, вызвав "WithName".

есть ли способ реализовать это или я пытаюсь использовать FluentValidation таким образом, что он не предназначен для использования?

3 ответов


взяли ее за правило для пытается создать свойство-уровень правило. Можно также использовать функцию AddRule для добавления правила общего назначения.

используя это, я создал составное доказательство правила концепции. Он принимает набор других валидаторов и запускает их. The yield break код пришел сразу с FluentValidator ' s DelegateValidator. Я не был уверен, что с ним делать, поэтому я схватил это из источника. Я не проследил его полное назначение, но все, кажется, работает как есть :)

код

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()));
    }
}

Базовый Тест:

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

    }

надеюсь, это поможет.


другой возможностью было бы переопределить Validate:

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);
}

вы можете использовать наборы правил для применения различных типов проверки, если это помогает в том, что вы пытаетесь сделать:

Наборы Правил FluentValidation