【问题标题】:Fluent Validator WithMessage and singleton instanceFluentvalidation WithMessage 和单例实例
【发布时间】:2023-03-09 10:30:01
【问题描述】:

在我正在工作的 MVC 项目中,我使用 Fluent Validation 来实现验证逻辑和统一作为依赖注入容器

在我的验证器类中有一些复杂的业务验证规则

public class ServicerRequestViewModelValidator : AbstractValidator<ServiceRequestViewModel>
{
    public ServiceRequestViewModelValidator(ILocalizationService localizationService)
    {
     RuleFor(x => x.IdStato).NotNull().WithMessage(string.Format(localizationService.GetMessage("Validation.General.MandataryField"), localizationService.GetMessage("ServiceRequestDetail.State")));
      // other business validations rule with localized error message
    }   
}

规则设置根据用户语言本地化的错误消息

杰里米斯金纳说:

验证器的实例化是一个昂贵的过程,因为 RuleFor 中的表达式树编译和解析 定义。因此,建议您使用验证器 实例作为单例 - 一旦实例化它们应该被缓存并 重用,而不是被多次实例化。

验证器不包含任何共享状态,因此它也应该是安全的 也可以在多线程场景中重用它们。最好的方法 缓存验证器实例将使用 IoC 容器(例如, StructureMap) 来管理实例生命周期。

所以我用 ContainerControlledLifetimeManager (singleton) 在容器中注册了验证器

container.RegisterType<IValidator<ServiceRequestViewModel>, ServiceRequestViewModelValidator>(new ContainerControlledLifetimeManager());

但是这样做会出现问题: 第一次解析ServiceRequestViewModelValidator 时,构造函数被执行,本地化的错误消息将根据用户的语言进行缓存,后续用户将根据实例化单例类的用户的语言获取本地化的消息。

【问题讨论】:

    标签: c# asp.net asp.net-mvc validation fluentvalidation


    【解决方案1】:

    我创建了一个新的WithMessage 扩展方法,它接收一个字符串的委托,利用LazyStringSource

     public static IRuleBuilderOptions<T, TProperty> WithMessage<T, TProperty>(this IRuleBuilderOptions<T, TProperty> rule, Func<string> errorMessage)
            {
                return rule.Configure((Action<PropertyRule>)(config =>
                {
                    config.CurrentValidator.ErrorMessageSource = (IStringSource)new  LazyStringSource(errorMessage);
                }));
            }
    

    然后我像这样更改了我的 ServiceRequestValidator:

    public class ServicerRequestViewModelValidator : AbstractValidator<ServiceRequestViewModel>
    {
             public ServiceRequestViewModelValidator(ILocalizationService localizationService)
                {
                       RuleFor(x => x.IdStato).NotNull().WithMessage(()=>string.Format(localizationService.GetMessage("Validation.General.MandataryField"), localizationService.GetMessage("ServiceRequestDetail.State")));
                }
            }
    

    在构造函数中这样做是设置将在验证过程中调用的委托,以根据用户语言而不是直接本地化错误消息字符串来解决本地化错误消息。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-18
      相关资源
      最近更新 更多