У меня есть ViewModel (BarViewModel
) с несколькими свойствами (Owner
, Customer
) типа Person
. Я хочу, чтобы один пользовательский валидатор (PersonValidator
) проверял эти свойства. Я хочу получить доступ к DisplayAttribute
этих Person
свойств в пользовательском валидаторе. Но я получаю null в результате для PropertyName
, если я использую пользовательский валидатор, но не если я использую проверку непосредственно в BarViewModelValidator
. Как я могу получить доступ к DisplayAttribute
в моем пользовательском валидаторе?
Результат для переменной errors
:
" должен быть старше 18 лет. (Детский валидатор)"
«Клиент должен быть старше 18 лет. (Родительский валидатор)»
[TestFixture]
public class BarViewModelTests
{
public class BarViewModel
{
[Display(Name = "Owner of bar")]
public Person Owner { get; set; } = new Person();
[Display(Name = "A Customer")]
public Person Customer { get; set; } = new Person();
}
public class Person
{
public int Age { get; set; }
}
public class PersonValidator : AbstractValidator<Person>
{
public PersonValidator()
{
RuleFor(p => p).Custom((_, context) =>
{
if ((context.InstanceToValidate as Person)!.Age < 18)
{
context.AddFailure($"{context.PropertyName}.{nameof(Person.Age)}", $"{context.DisplayName} must be over 18 years. (Child Validator)");
}
});
}
}
public class BarViewModelValidator : AbstractValidator<BarViewModel>
{
public BarViewModelValidator()
{
RuleFor(p => p.Owner).SetValidator(new PersonValidator());
RuleFor(p => p.Customer).SetValidator(new PersonValidator());
RuleFor(p => p.Customer).Custom((_, context) =>
{
if ((context.InstanceToValidate as BarViewModel)!.Customer.Age < 18)
{
context.AddFailure($"{context.PropertyName}.{nameof(Person.Age)}", $"{context.DisplayName} must be over 18 years. (Parent Validator)");
}
});
}
}
private BarViewModelValidator _validator;
[SetUp]
public void Setup()
{
_validator = new BarViewModelValidator();
}
[Test]
public void Should_have_proper_display_name()
{
var model = new BarViewModel
{
Owner = new Person
{
Age = 20
},
Customer = new Person
{
Age = 15
}
};
var errors = _validator.TestValidate(model).Errors;
}
}
Я знаю, что это сработает, но я не хочу решать проблему так:
public class PersonValidator : AbstractValidator<Person>
{
public PersonValidator(string displayName)
{
RuleFor(p => p).Custom((_, context) =>
{
if ((context.InstanceToValidate as Person)!.Age < 18)
{
context.AddFailure($"{context.PropertyName}.{nameof(Person.Age)}", $"{displayName} must be over 18 years. (Child Validator)");
}
});
}
}
public class BarViewModelValidator : AbstractValidator<BarViewModel>
{
public BarViewModelValidator()
{
RuleFor(p => p.Owner).SetValidator(new PersonValidator("Owner of bar"));
RuleFor(p => p.Customer).SetValidator(new PersonValidator("A Customer"));
}
}
Дочерние валидаторы не знают о родительском валидаторе, поэтому они не могут получить доступ к имени родительского свойства таким образом. Итак, осталось три варианта:
SetValidator()