c# - Fluentvalidation WithMessage 和单例实例

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

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

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

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 说:

Instantiation of validators is an expensive process due to the expression tree compilation and parsing within the RuleFor definitions. Because of this, it's recommended that you use validator instances as singletons- once instantiated they should be cached and reused, rather than being instantiated multiple times.

Validators do not contain any shared state, so it should also be safe to reuse them in multithreaded scenarios too. The best approach to caching the validator instances would be to use an IoC container (eg, StructureMap) to manage the instance lifecycles.

所以我在容器中注册了带有 ContainerControlledLifetimeManager 的验证器(单例)

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

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

最佳答案

我创建了一个新的 WithMessage 扩展方法,它接收一个代替字符串的委托(delegate),利用了 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")));
            }
        }

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

关于c# - Fluentvalidation WithMessage 和单例实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42365741/

相关文章:

ASP.net:在 ASP.net 网页中显示 PDF

c# - 如何在 C# MVC 中创建动态复选框列表组?

c# - 如何获取在 asp.net 中使用我的 web api 的请求 url?

c# - 我应该担心内存泄漏吗?

c# - 什么会导致 XML 文件被空字符填充?

c# - 添加 datagridviewcolumn 属性 designtime

jquery - 如果执行 document.html.style.display= '' ,为什么我的网站主页仍为空白?

c# - 为什么我不能在调试器中编辑包含匿名方法的方法?

c# - EF : detach vs. 预加载与 noTracking

ASP.Net/Ruby/PHP MVC 网站、jQuery Mobile 和 Phonegap