2017-02-21 4 views
2

В проекте им MVC работает Я использую Fluent Validation реализовать логику проверки и единство, как инъекции зависимостей контейнерсвободного Validator WithMessage и синглтон экземпляр

В моем классе валидатора есть некоторые сложные правила проверки бизнеса

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 разрешен конструктор выполняется и локализованное сообщение об ошибке будет кэшироваться в соответствии с языком пользователя, а последующие пользователи получат сообщение локализованным в соответствии с языком пользователя, который создавал экземпляр класса singleton.

ответ

0

Я создал новый WithMessage метод расширения, который riceve делегат InstEd строки, воспользовавшись 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"))); 
      } 
     } 

Делать подобное в конструкторе задается делегат, который будет вызывать во время процесса проверки для разрешения локализованного сообщения об ошибке на основе языка пользователя, а не непосредственно строки локализованного сообщения об ошибке.

Смежные вопросы