如何正确地使用Simple Injector注册FluentValidation?

7
我能够使用FluentValidatorFactory注册AbstractValidators的程序集。然而,这种方式并不对,因为并非所有IoC容器都是在引导/组合根期间进行注册。取而代之的是,Fluent validators由一个单独的工厂进行注册: 组合根:
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);
    }
}

一个仅依赖于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;
    }
}

一个适用于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();
    }
}

SimpleInjector对开放式泛型有很好的支持,我的所有流畅验证器类的签名都类似于以下内容:
public class SomeClassValidator : AbstractValidator<SomeClass>
{
    public SomeClassValidator([depedencies injected here])
    {
        // ... set up validation rules
    }
}

那么,在引导程序/组合根中注册验证器是否有更好的方法,而不是使用Fluent的验证器工厂?

P.S. @DotNetJunkie -- 如果您在simpleinjector.codeplex.com上有关于此的维基页面,那就太棒了。


你为什么要将容器包装在一个“SimpleDependencyInjector”抽象中?这似乎是多余的。 - Steven
有关Fluent Validation的维基页面会太过特定于框架。可能有数百个框架都可以拥有维基页面;我们何时停止呢? - Steven
@Steven,SimpleDependencyInjector类是用于实现IServiceProvider的simpleinjector特定实现。我不想引用SI容器,就像在切换到SI之前没有引用IUnityContainer代码一样。 - danludwig
@Steven,关于wiki的问题你是正确的。事实上,你已经拥有了一个基本上解释我所问问题的wiki。我只是需要反复阅读几次才真正理解它:http://simpleinjector.codeplex.com/wikipage?title=Advanced-scenarios&referringTitle=Documentation#Registration_Of_Open_Generic_Types - danludwig
1个回答

10

我想我自己解决了这个问题。

1.) 在组合根中注册Fluent的开放式泛型IValidator<T>接口:

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);
    }
}

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;
    }
}

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

var injector = new SimpleDependencyInjector();
FluentValidationModelValidatorProvider.Configure(
    provider =>
    {
        provider.ValidatorFactory = new FluentValidatorFactory(injector);
    }
);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接