在 FluentValidation 的 CustomValidator 中访问 Parent DisplayName
Access Parent DisplayName in CustomValidator in FluentValidation
我有一个 ViewModel (BarViewModel
),它有几个类型为 Person
的属性(Owner
、Customer
)。我想要一个自定义验证器 (PersonValidator
) 来验证这些属性。我确实想访问自定义验证器中那些 Person
属性的 DisplayAttribute
。但是,如果我使用自定义验证器,PropertyName
的结果为 null,但如果我直接在 BarViewModelValidator
中使用验证,则不会。如何在我的自定义验证器中访问 DisplayAttribute
?
errors
变量的结果:
" 必须年满 18 岁。(Child 验证者)"
“客户必须年满 18 岁。(Parent 验证者)”
[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()
- 直接在父验证器中定义子规则
- 改为定义扩展并像子验证器一样使用它
我有一个 ViewModel (BarViewModel
),它有几个类型为 Person
的属性(Owner
、Customer
)。我想要一个自定义验证器 (PersonValidator
) 来验证这些属性。我确实想访问自定义验证器中那些 Person
属性的 DisplayAttribute
。但是,如果我使用自定义验证器,PropertyName
的结果为 null,但如果我直接在 BarViewModelValidator
中使用验证,则不会。如何在我的自定义验证器中访问 DisplayAttribute
?
errors
变量的结果:
" 必须年满 18 岁。(Child 验证者)"
“客户必须年满 18 岁。(Parent 验证者)”
[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()
- 直接在父验证器中定义子规则
- 改为定义扩展并像子验证器一样使用它