Подтвердить что ты не робот

Правило FluentValidation для нулевого объекта

Я пытался выяснить, как создать правило FluentValidation, которое проверяет, не является ли экземпляр объекта, который он проверяет, не является нулевым до проверки его свойств.

Я предпочел бы инкапсулировать эту нулевую проверку в Validator, а не делать ее в вызывающем коде.

См. пример кода ниже с комментариями, где требуется требуемая логика:

namespace MyNamespace
{
    using FluentValidation;

    public class Customer
    {
        public string Surname { get; set; }
    }

    public class CustomerValidator: AbstractValidator<Customer> 
    {
        public CustomerValidator() 
        {
            // Rule to check the customer instance is not null.

            // Don't continue validating.

            RuleFor(c => c.Surname).NotEmpty();
        }
    }

    public class MyClass
    {
        public void DoCustomerWork(int id)
        {
            var customer = GetCustomer(id);
            var validator = new CustomerValidator();

            var results = validator.Validate(customer);

            var validationSucceeded = results.IsValid;
        }

        public Customer GetCustomer(int id)
        {
            return null;
        }
    }
}

Итак, мой вопрос как я могу проверить конструктор CustomerValidator(), что текущий экземпляр клиента не является нулевым и прервать обработку дополнительных правил, если он равен null?

Спасибо заранее.

4b9b3361

Ответ 1

Вы можете переопределить метод Validate в классе CustomerValidator.

public class CustomerValidator: AbstractValidator<Customer> 
{
    // constructor...

    public override ValidationResult Validate(Customer instance)
    {
        return instance == null 
            ? new ValidationResult(new [] { new ValidationFailure("Customer", "Customer cannot be null") }) 
            : base.Validate(instance);
    }
}

Ответ 2

Я не могу проверить это прямо сейчас, но вы можете либо попробовать переопределить Validate, либо включить правила в блок When:

public CustomerValidator()
{
     When(x => x != null, () => {
                                   RuleFor(x => x.Surname).NotEmpty();
                                   //etc.
                                });
}

Ответ 3

Я унаследовал от абстрактного AbstractValidator и создал вместо этого класс NullReferenceAbstractValidator:

public class NullReferenceAbstractValidator<T> : AbstractValidator<T>
{
    public override ValidationResult Validate(T instance)
    {
        return instance == null
            ? new ValidationResult(new[] { new ValidationFailure(instance.ToString(), "response cannot be null","Error") })
            : base.Validate(instance);
    }
}

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

public class UserValidator : NullReferenceAbstractValidator<User>

Ответ 4

Поскольку приведенные выше решения не сработали для меня (FluentValidation, Version = 6.2.1.0 для Net45), я отправляю то, что я сделал. Это просто простая замена/обертка для метода расширения ValidateAndThrow.

public static class ValidatorExtensions
{
    public static void ValidateAndThrowNotNull<T>(this IValidator<T> validator, T instance)
    {
        if (instance == null)
        {
            var validationResult = new ValidationResult(new[] { new ValidationFailure("", "Instance cannot be null") });
            throw new ValidationException(validationResult.Errors);
        }
        validator.ValidateAndThrow(instance);
    }
}

Ответ 5

Для тех, кто использует версию > 6.2.1, вам нужно переопределить эту подпись, чтобы добиться того же, что и @chrispr:

public override ValidationResult Validate(ValidationContext<T> context)
{
    return (context.InstanceToValidate == null) 
        ? throw new ValidationResult(new[] { new ValidationFailure("Property", "Error Message") })
        : base.Validate(context);       
}

Ответ 6

Используйте каскадный режим.

Вот пример из документации.

RuleFor(x => x.Surname).Cascade(CascadeMode.StopOnFirstFailure).NotNull().NotEqual("foo");

Также из документации:

Если отказоустойчивость NotNull не выполняется, то средство проверки NotEqual не будет казнены. Это особенно полезно, если у вас сложная цепочка где каждый валидатор зависит от предыдущего валидатора для успеха.

Ответ 7

Переопределить EnsureInstanceNotNull, как показано ниже

protected override void EnsureInstanceNotNull(object instanceToValidate)
{
    if(instanceToValidate==null)
      throw new ValidationException("Customer can not be null");
}