Обзор библиотеки FluentValidation. Часть 5. Условия

9db201ed5b95a21a8ef8859622cb5496.png

Вы можете задавать условия через методы расширения When и Unless для определения, должны ли выполняться все предыдущие валидаторы (до вызова метода расширения) либо конкретный валидатор в правиле RuleFor. Применение метода расширения When:

// Модель клиента
public class Customer
{
  // Имя
  public string? Forename { get; set; }
  // Фамилия
  public string? Surname { get; set; }
}

// Валидатор для модели клиента
public class CustomerValidator : AbstractValidator
{
  public CustomerValidator()
  {
    // Оба свойства (Surname, Forename) должны быть заполнены, если заполнено одно из них
    RuleFor(customer => customer.Surname)
      .NotNull()
      .When(customer => customer.Forename is not null);

    RuleFor(customer => customer.Forename)
      .NotNull()
      .When(customer => customer.Surname is not null);
  }
}

Метод расширения Unless противоположность методу расширения When, следующий пример кода вернёт тот же результат, что из примера выше, т. к. условие инвертировано:

// Модель клиента
public class Customer { ... }

// Валидатор для модели клиента
public class CustomerValidator : AbstractValidator
{
  public CustomerValidator()
  {
    // Оба свойства (Surname, Forename) должны быть заполнены, если заполнено одно из них
    RuleFor(customer => customer.Surname)
      .NotNull()
      .Unless(customer => customer.Forename is null);

    RuleFor(customer => customer.Forename)
      .NotNull()
      .Unless(customer => customer.Surname is null);
  }
}

По умолчанию FluentValidaton применяет условие When, Unless для всех предыдущих валидаторов в правиле RuleFor. Если возникла необходимость указать условие к валидатору, который непосредственно предшествует методу расширения When, Unless нужно это явно указать через значение перечисления ApplyConditionTo.CurrentValidator, которое передаётся вторым аргументом в метод расширения When, Unless, пример использования с методом расширения When:

// Модель клиента
public class Customer
{
  // Название организации
  public string? OrgName { get; set; }
  // Имя
  public string? Forename { get; set; }
  // Фамилия
  public string? Surname { get; set; }
}

// Валидатор для модели клиента
public class CustomerValidator : AbstractValidator
{
  public CustomerValidator()
  {
    // Должны быть заполнены поля Surname, Forename (одновременно) либо OrgName
    RuleFor(customer => customer.Surname)
      .NotNull()
        .When(customer => customer.OrgName is null && customer.Forename is not null, ApplyConditionTo.CurrentValidator)
      .Null()
        .When(customer => customer.OrgName is not null && customer.Forename is null, ApplyConditionTo.CurrentValidator);

    RuleFor(customer => customer.Forename)
      .NotNull()
        .When(customer => customer.OrgName is null && customer.Surname is not null, ApplyConditionTo.CurrentValidator)
      .Null()
        .When(customer => customer.OrgName is not null && customer.Surname is null, ApplyConditionTo.CurrentValidator);

      RuleFor(customer => customer.OrgName)
        .NotNull()
          .When(customer => customer.Surname is null && customer.Forename is null, ApplyConditionTo.CurrentValidator)
        .Null()
          .When(customer => customer.Surname is not null && customer.Forename is not null, ApplyConditionTo.CurrentValidator);
  }
}

Обратите внимание, что я выделил дополнительной табуляцией вызов метода расширения When, т. к. указан аргумент ApplyConditionTo.CurrentValidator, чтобы подчеркнуть принадлежность метода расширения When только к предыдущему валидатору.

Если второй параметр ApplyConditionTo явно не указан, он примет значение ApplyConditionTo.AllValidators по умолчанию, которое означает, что условие применяется для всех предыдущих валидаторов в правиле RuleFor.

Если возникла необходимость указать общее условие для группы правил RuleFor, можно использовать метод When «верхнего уровня» (из базового класса AbstractValidator) вместо метода расширения When, который крепится в конце правила либо валидатора:

// Модель клиента
public class Customer { ... }

// Валидатор для модели клиента
public class CustomerValidator : AbstractValidator
{
  public CustomerValidator()
  {
    // Должны быть заполнены поля Surname, Forename (одновременно) либо OrgName.
    // Если OrgName не заполнен, то
    When(customer => customer.OrgName is null, () =>
    {
      // Surname должен быть заполнен
      RuleFor(customer => customer.Surname)
        .NotNull();
      // Forename должен быть заполнен
      RuleFor(customer => customer.Forename)
        .NotNull();
      // OrgName должен быть не заполнен
      RuleFor(customer => customer.OrgName)
        .Null();
    })
    // Otherwise выполняется в случае, если условие When не удовлетворено (false)
    .Otherwise(() =>
    {
      // Surname должен быть не заполнен
      RuleFor(customer => customer.Surname)
        .Null();
      // Forename должен быть не заполнен
      RuleFor(customer => customer.Forename)
        .Null();
      // OrgName должен быть заполнен
      RuleFor(customer => customer.OrgName)
        .NotNull();
    });
  }
}

Вызов метода Otherwise опционален, его можно вызывать непосредственно после вызова When «верхнего уровня». Выполняется в случае, если условие When не удовлетворено (false).

← Предыдущая часть

© Habrahabr.ru