【问题标题】:FluentValidation as a serviceFluentValidation 即服务
【发布时间】:2011-01-26 21:44:52
【问题描述】:

我正在使用 FluentValidation 2 来验证某些实体。我想创建一个IValidationService,我可以将其传递给其他服务以允许它们执行验证。我想这样暴露它:

public interface IValidationEngine
{
    IEnumerable<ValidationError> Validate<T>(T entity);
}

ValidationError 是一个封装我的验证错误的类。理想情况下,我不想将特定验证器暴露给我的一项服务(例如OrderValidator)。我希望验证服务能够构建/找到正确的验证器。 FV 是否内置了任何东西来定位特定类型的验证器(并且它在内部缓存)?或者,我是否必须走IValidatorFactory 路线,然后将每个验证器与我的 IoC 容器连接起来?

【问题讨论】:

    标签: c# .net fluentvalidation


    【解决方案1】:

    我已经设法用IValidatorFactory 方法解决了这个问题。我正在使用 Ninject,因此需要更改下面的特定 IoC 详细信息。

    public interface IValidationService
    {
        IEnumerable<ValidationError> Validate<T>(T entity)
            where T : class;
    }
    
    public class FluentValidationService : IValidationService
    {
        private readonly IValidatorFactory validatorFactory;
    
        public FluentValidationService(IValidatorFactory validatorFactory)
        {
            this.validatorFactory = validatorFactory;
        }
    
        public IEnumerable<ValidationError> Validate<T>(T entity)
            where T : class
        {
            var validator = this.validatorFactory.GetValidator<T>();
            var result = validator.Validate(entity);
            return result.Errors.Select(e => new ValidationError(e.PropertyName, e.ErrorMessage));
        }
    }
    
    // Then implement FV's IValidatorFactory:
    
    public class NinjectValidatorFactory : ValidatorFactoryBase
    {
        private readonly IKernel kernel;
    
        public NinjectValidatorFactory(IKernel kernel)
        {
            this.kernel = kernel;
        }
    
        public override IValidator CreateInstance(Type validatorType)
        {
            return kernel.TryGet(validatorType) as IValidator;
        }
    }
    
    // I then wire both of these in a Ninject Module:
    
    public class ValidationModule : NinjectModule
    {
        public override void Load()
        {
            this.Bind<IValidationService>().To<FluentValidationService>().InRequestScope(); // Specific to MVC.
            this.Bind<IValidatorFactory>().To<NinjectValidatorFactory>().InRequestScope();
        }
    }
    
    // Then I can use it inside a service:
    
    public class FooService
    {
        private readonly IValidationService validationService;
    
        public FooService(IValidationService validationService)
        {
            this.validationService = validationService;
        }
    
        public bool Add(Foo foo)
        {
            if(this.validationService.Validate(foo).Any())
            {
                // Handle validation errors..
            }
    
            // do other implementation details here.
        }
    }
    

    【讨论】:

    • 您还必须绑定您的验证器,这可以像这样自动完成:AssemblyScanner.FindValidatorsInAssembly(Assembly.GetExecutingAssembly()) .ForEach(match => Bind(match.InterfaceType).To( match.ValidatorType));
    • 您的实际验证器类是什么样的?我看不出这如何与 IValidator 一起使用,因为 AbstractValidator 是通用的并且与接口 IValidator. 匹配
    猜你喜欢
    • 2012-08-25
    • 2023-01-03
    • 2012-09-25
    • 2017-06-28
    • 2019-03-19
    • 1970-01-01
    • 2013-01-31
    • 2017-04-02
    • 1970-01-01
    相关资源
    最近更新 更多