Свободные правила проверки, подмножества и вложенность - PullRequest
2 голосов
/ 09 марта 2012

Учитывая класс валидатора, который выглядит следующим образом

 public class SomeValidator : AbstractValidator<SomeObject>
 {
      public SomeValidator(){
           RuleSet("First",
                () => {
                     RuleFor(so => so.SomeMember).SetValidator(new SomeMemberValidator())
           });
           RuleSet("Second",
                () => ... Code Does Not Matter ... );
           RuleSet("Third",
                () => ... Code Does Not Matter ... );
      }
 }

И еще один, чтобы выполнить внутреннюю проверку члена

 public class SomeMemberValidator: AbstractValidator<SomeMember>
 {
      public SomeValidator(){
           RuleSet("Fourth",
                () => {
                     ... Code Does Not Matter ...
           });
      }
 }

Вопрос в том, что я хочу запустить определенные наборы правил: «Первый», «Второй» и «Четвертый».Я не хочу, чтобы "Third" запускался.

Учитывая, что сигнатура метода Validate принимает только один аргумент набора правил, я не вижу никакого способа сделать это.Есть "*", но я не хочу запускать все правила.

Пожалуйста, помогите.

Ответы [ 2 ]

6 голосов
/ 23 марта 2012

Вы можете использовать конструктор валидатора вместо RuleSet в качестве обходного пути для этой проблемы.Просто создайте перечисление внутри класса валидатора и затем используйте его значение при создании валидатора.

Таким образом, корректные правила будут активированы в зависимости от того, какой режим установлен в конструкторе.

public class UserValidator : AbstractValidator<User>
{
    public enum Mode
    {
        Create,
        Edit
    }

    public UserValidator()
    {
        // Default rules...
    }

    public UserValidator(UserValidator.Mode mode)
        : this()
    {
        if (mode == Mode.Edit)
        {
            // Rules for Edit...

            RuleFor(so => so.SomeMember)
                .SetValidator(
                    new SomeMemberValidator(SomeMemberValidator.Mode.SomeMode))
        }

        if (mode == Mode.Create)
        {
            // Rules for Create...

            RuleFor(so => so.SomeMember)
                .SetValidator(
                    new SomeMemberValidator())
        }
    }
}

Я думаюна самом деле это более гибкий метод, чем использование RuleSet.

Существует только одна небольшая проблема, связанная с интеграцией FluentValidation MVC: User класс не может иметь атрибут [Validator(typeof(UserValidator))], потому что UserValidator будет создан с использованием конструктора по умолчанию, передможет делать все что угодно в методе контроллера.

Validator должен быть создан и вызван вручную.Вот так например:

public class UserController : Controller
{
    [HttpPost]
    public ActionResult Create(User userData)
    {
        var validator = new UserValidator(UserValidator.Mode.Create);

        if (ValidateWrapper(validator, userData, this.ModelState))
        {
            // Put userData in database...
        }
        else
        {
            // ValidateWrapper added errors from UserValidator to ModelState.
            return View();
        }
    }

    private static bool ValidateWrapper<T>(FluentValidation.AbstractValidator<T> validator, T data, ModelStateDictionary modelState)
    {
        var validationResult = validator.Validate(data);

        if (!validationResult.IsValid)
        {
            foreach (var error in validationResult.Errors)
                modelState.AddModelError(error.PropertyName, error.ErrorMessage);

            return false;
        }

        return true;
    }
}
5 голосов
/ 09 марта 2012

Вы можете выполнить более одного RuleSet, но я не думаю, что вы можете выполнить внутренний RuleSet.

validator.Validate(new ValidationContext<SomeObject>(person, new PropertyChain(), new RulesetValidatorSelector("First", "Second", "Fourth")));

Источник

Другой вариант - исследовать исходный код и попытаться придумать способ сделать это. Третий параметр ValidationContext - это интерфейс, IValidatorSelector, может быть, вам удастся создать собственный класс.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...