在我工作的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>
答案 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")));
}
}
在构造函数中执行类似操作,设置将在验证过程中调用的委托,以根据用户语言解析本地化错误消息,而不是直接解析本地化错误消息字符串。