You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 19:58:25