FluentValidation 11.6.0自定义验证器:服务注入与动态占位符提示
问题场景
现有Customer类包含以下属性:
public string RegistrationNr public bool Archived
已实现AddCustomerValidator验证器且运行正常:
internal sealed class AddCustomerValidator : AbstractValidator<AddCustomerViewModel> { private readonly ICustomerService _customerService; public AddCustomerValidator(ICustomerService customerService) { _customerService = customerService; RuleFor(c => c.RegistrationNumber) .Must((registrationNumber) => { var customer = _customerService.FindByRegistrationNumber(registrationNumber); return customer == null; }) .WithMessage("Number already in use."); } }
当前使用FluentValidation 11.6.0,需要根据已存在客户的Archived状态生成更精准的提示消息:"Number already in use for active customer"或"Number already in use for archived customer"。尝试编写自定义静态验证器类时,无法识别_customerService,需解决服务传递/注入的问题。
解决方案
方法一:直接修改原有验证器(推荐)
无需额外编写静态类,利用Must的重载获取验证上下文,直接将客户状态注入消息格式化器:
internal sealed class AddCustomerValidator : AbstractValidator<AddCustomerViewModel> { private readonly ICustomerService _customerService; public AddCustomerValidator(ICustomerService customerService) { _customerService = customerService; RuleFor(c => c.RegistrationNumber) .Must((registrationNumber, context) => { // 按原有逻辑格式化注册编号 var formattedRegNr = AfvoerCheckCommon.Formatters.Formatter.FormatRegNr(registrationNumber); var customer = _customerService.FindByRegistrationNumber(formattedRegNr); if (customer == null) return true; // 将客户状态添加到消息格式化器参数中 context.MessageFormatter.AppendArgument("CustomerStatus", customer.Archived ? "archived" : "active"); return false; }) .WithMessage("Number already in use for {CustomerStatus} customer."); } }
这种方式直接在原有验证器内完成逻辑,避免了静态类的依赖问题,代码更简洁易维护。
方法二:修改自定义静态验证器
如果坚持使用静态扩展方法,需将ICustomerService作为参数传入(静态类无法直接依赖注入):
1. 更新静态验证器类
public static class MyCustomValidators { // 添加ICustomerService作为扩展方法的参数 public static IRuleBuilderOptions<T, string> RegistrationNumberExists<T>( this IRuleBuilder<T, string> rulebuilder, ICustomerService customerService) { return rulebuilder.Must((rootObject, registrationNumber, context) => { var formattedRegNr = AfvoerCheckCommon.Formatters.Formatter.FormatRegNr(registrationNumber); var customer = customerService.FindByRegistrationNumber(formattedRegNr); if (customer == null) return true; context.MessageFormatter.AppendArgument("CustomerStatus", customer.Archived ? "archived" : "active"); return false; }) .WithMessage("Number already in use for {CustomerStatus} customer."); } }
2. 在验证器中调用扩展方法
internal sealed class AddCustomerValidator : AbstractValidator<AddCustomerViewModel> { private readonly ICustomerService _customerService; public AddCustomerValidator(ICustomerService customerService) { _customerService = customerService; // 将注入的服务实例传递给扩展方法 RuleFor(c => c.RegistrationNumber) .RegistrationNumberExists(_customerService); } }
内容的提问来源于stack exchange,提问作者Jeroen E
相关产品推荐
相关产品推荐

