使用SimpleInjector注册FluentValidation的正确方法是什么?

dan*_*wig 7 dependency-injection fluentvalidation fluentvalidation-2.0 open-generics simple-injector

我可以AbstractValidators使用a 注册FluentValidation FluentValidatorFactory.但是,它感觉不对,因为并非所有IoC容器注册都在bootstrap/composition root期间发生.相反,流利的验证器由一个单独的工厂注册:

所述组合物根:

public class SimpleDependencyInjector : IServiceProvider
{
    public readonly Container Container;

    public SimpleDependencyInjector()
    {
        Container = Bootstrap();
    }

    internal Container Bootstrap()
    {
        var container = new Container();

        container.Register< // ...register all non-fluent-validator types, then

        container.Verify();
        return container;
    }

    public object GetService(Type serviceType)
    {
        return ((IServiceProvider)Container).GetService(serviceType);
    }
}
Run Code Online (Sandbox Code Playgroud)

一个抽象的流利验证工厂,仅依赖于IServiceProvider

public abstract class FluentValidatorFactory : ValidatorFactoryBase
{
    private IServiceProvider Injector { get; set; }

    protected FluentValidatorFactory(IServiceProvider injector)
    {
        Injector = injector;
    }

    public override IValidator CreateInstance(Type validatorType)
    {
        return Injector.GetService(validatorType) as IValidator;
    }
}
Run Code Online (Sandbox Code Playgroud)

一个流畅的验证工厂实现了SimpleInjector

public class SimpleValidatorFactory : FluentValidatorFactory
{
    public SimpleValidatorFactory(SimpleDependencyInjector injector) 
        : base(injector)
    {
        var validators = AssemblyScanner.FindValidatorsInAssembly(
            Assembly.GetCallingAssembly());
        validators.ForEach(validator => 
            injector.Container.Register(
                validator.InterfaceType, validator.ValidatorType));
        injector.Container.Verify();
    }
}
Run Code Online (Sandbox Code Playgroud)

SimpleInjector对开放泛型有很好的支持,我所有的流畅验证器类都有类似如下的签名:

public class SomeClassValidator : AbstractValidator<SomeClass>
{
    public SomeClassValidator([depedencies injected here])
    {
        // ... set up validation rules
    }
}
Run Code Online (Sandbox Code Playgroud)

那么,有没有更好的方法在bootstrap/composition根目录中注册验证器,而不是使用fluent的验证器工厂?

PS @DotNetJunkie - 如果你在simpleinjector.codeplex.com上一个wiki页面会很棒.

dan*_*wig 10

我想我自己想出来了.

1.)IValidator<T>在组合根中注册fluent的开放通用接口:

public class SimpleDependencyInjector : IServiceProvider
{
    public readonly Container Container;

    public SimpleDependencyInjector()
    {
        Container = Bootstrap();
    }

    internal Container Bootstrap()
    {
        var container = new Container();

        // some container registrations

        var assemblies = AppDomain.CurrentDomain.GetAssemblies().ToList();
        container.RegisterManyForOpenGeneric(typeof(IValidator<>), assemblies);

        // some more registrations

        container.Verify();
        return container;
    }

    public object GetService(Type serviceType)
    {
        return ((IServiceProvider)Container).GetService(serviceType);
    }
}
Run Code Online (Sandbox Code Playgroud)

2.)摆脱SimpleValidatorFactory班级.

3.)制作FluentValidatorFactory一个非抽象的具体课程:

public class FluentValidatorFactory : ValidatorFactoryBase
{
    private IServiceProvider Injector { get; set; }

    public FluentValidatorFactory(IServiceProvider injector)
    {
        Injector = injector;
    }

    public override IValidator CreateInstance(Type validatorType)
    {
        return Injector.GetService(validatorType) as IValidator;
    }
}
Run Code Online (Sandbox Code Playgroud)

4.)在Global.asax中注册FluentValidatorFactory作为验证工厂提供者:

var injector = new SimpleDependencyInjector();
FluentValidationModelValidatorProvider.Configure(
    provider =>
    {
        provider.ValidatorFactory = new FluentValidatorFactory(injector);
    }
);
Run Code Online (Sandbox Code Playgroud)