FluentValidation несколько валидаторов

Могу ли я добавить более одного валидатора к объекту? Например:

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

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

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

public class BarValidator : AbstractValidator
{
    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
{
    public FooBarValidator()
    {
        RuleFor(x => x)
            .SetValidator(new FooValidator())
            .SetValidator(new BarValidator());
    }
}

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

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

Я получаю:InvalidOperationException

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

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

Ответы на вопрос(3)

и, если это помогает в том, что вы пытаетесь сделать:

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

 Bjarki Heiðar02 нояб. 2012 г., 16:45
RuleSets не подходит. Я всегда хотел бы запустить все правила проверки. Я'я пытаюсь создать DTO 's, которые имеют много одинаковых свойств, поэтому было бы неплохо повторно использовать валидаторы без вложенных свойств obj в DTO.

Другой возможностью было бы переопределить 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);
}
</validationfailure></foobar>
Решение Вопроса

но использовать функцию 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()));
    }
}
</foobar></servicestack.fluentvalidation.validators.ipropertyvalidator></servicestack.fluentvalidation.results.validationfailure></servicestack.fluentvalidation.results.validationfailure></ibar></ifoo>
Базовый контрольный пример:
    [TestMethod]
    public void TestValidator()
    {
        FooBarValidator validator = new FooBarValidator();
        var result = validator.Validate(new FooBar());

    }

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

 Eli Gassert02 нояб. 2012 г., 19:06
Немного подумав, вы можете автоматически найти все валидаторы, с которыми должен соединяться составной валидатор (то есть найти все интерфейсы и цепочки базовых классов и посмотреть, есть ли там 's IValidator <T> для них и, если да, автоматически добавить его в список). Все зависит от того, как далеко вы хотите это сделать. Я'Я, вероятно, предпочел бы использовать отражение, чтобы найти все валидаторы вместо списка вручную.
 Andrew12 янв. 2018 г., 13:41
Этот ответ, хотя он все еще работает (с небольшими изменениями), довольно старый. Есть ли встроенный способ сделать это еще? Ближе всего я смог найти "Включают" метод, который был добавлен, но он позволяет включать только IValidators того же типа, что и тот, который выполняет включение, так чтоt использоваться для нескольких интерфейсов в соответствии с примером выше.

Ваш ответ на вопрос