Как правильно зарегистрировать FluentValidation в SimpleInjector? - PullRequest
7 голосов
/ 03 апреля 2012

Я могу зарегистрировать FluentValidation AbstractValidators, используя FluentValidatorFactory. Однако он не чувствует себя правильным, потому что не все регистрации контейнера IoC происходят во время начальной загрузки / создания корня. Вместо этого текущие валидаторы зарегистрированы отдельной фабрикой :

Композиция корень композиции :

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

A свободная реализация фабрики валидатора для 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 .

1 Ответ

10 голосов
/ 03 апреля 2012

Кажется, я сам все понял.

1.) Зарегистрируйте открытый общий интерфейс 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 class.

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.) Зарегистрируйте FluentValidatorFactory в качестве поставщика фабрики валидации в global.asax:

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