Правило FluentValidation для нулевого объекта
Я пытался выяснить, как создать правило FluentValidation, которое проверяет, не является ли экземпляр объекта, который он проверяет, нулевым, до проверки его свойств.
Я бы предпочел инкапсулировать эту нулевую проверку в валидатор, а не делать это в вызывающем коде.
см. пример кода ниже с комментариями, где требуется логика:
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() конструктор, что текущий экземпляр customer не является null и прервать дальнейшую обработку правил, если она равна null?
спасибо заранее.
8 ответов
вы должны иметь возможность переопределить 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);
}
}
Я не могу проверить это прямо сейчас, но вы можете попытаться переопределить Validate
, или включить правила в When
блок:
public CustomerValidator()
{
When(x => x != null, () => {
RuleFor(x => x.Surname).NotEmpty();
//etc.
});
}
для тех, кто использует версию >6.2.1, вам нужно переопределить эту подпись, чтобы достичь того же, что и @chrispr:
public override ValidationResult Validate(ValidationContext<T> context)
{
return (context.InstanceToValidate == null)
? new ValidationResult(new[] { new ValidationFailure("Property", "Error Message") })
: base.Validate(context);
}
я унаследовал от fluent 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>
поскольку вышеуказанные решения не работали для меня (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);
}
}
используйте каскадный режим.
вот пример документация.
RuleFor(x => x.Surname).Cascade(CascadeMode.StopOnFirstFailure).NotNull().NotEqual("foo");
также из документации:
если валидатор NotNull не выполняется, то валидатор NotEqual не будет выполненный. Это особенно полезно, если у вас сложная цепочка где каждый валидатор зависит от предыдущего валидатора для успеха.
переопределить EnsureInstanceNotNull как показано ниже
protected override void EnsureInstanceNotNull(object instanceToValidate)
{
if(instanceToValidate==null)
throw new ValidationException("Customer can not be null");
}
С помощью Custom (). Это также может быть очень полезно, когда проверка другого поля основана на проверке вашего текущего поля.
ruleBuilder.Custom((obj, context) =>
{
if (obj != null)
{
var propertyName = <field where should be validation>;
context.AddFailure(propertyName, "'Your field name' Your validation message.");
}
});