Доступ к Parent DisplayName в CustomValidator в FluentValidation

У меня есть 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"));
        }
    }
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
549
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Дочерние валидаторы не знают о родительском валидаторе, поэтому они не могут получить доступ к имени родительского свойства таким образом. Итак, осталось три варианта:

  • чтобы явно передать его через конструктор и использовать SetValidator()
  • чтобы определить дочерние правила непосредственно внутри родительского валидатора
  • вместо этого определить расширение и использовать его аналогично дочернему валидатору

Другие вопросы по теме