Fluent Validator WithMessage和singleton实例

时间:2017-02-21 11:13:02

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

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

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

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
    }   
}

规则设置根据用户语言

进行本地化的错误消息

JeremySkinner说:

  

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

     

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

所以我在容器中使用ContainerControlledLifetimeManager(singleton)

注册了验证器
container.RegisterType<IValidator<ServiceRequestViewModel>, ServiceRequestViewModelValidator>(new ContainerControlledLifetimeManager());

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

1 个答案:

答案 0 :(得分:0)

我创建了一个新的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")));
            }
        }

在构造函数中执行类似操作,设置将在验证过程中调用的委托,以根据用户语言解析本地化错误消息,而不是直接解析本地化错误消息字符串。