Как правильно зарегистрировать FluentValidation в SimpleInjector?
Я могу зарегистрировать 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;
}
}
Свободная реализация фабрики валидаторов для 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?
PS @DotNetJunkie - было бы здорово, если бы у вас была вики-страница по этому адресу simpleinjector.codeplex.com.
1 ответ
Я думаю, что я понял это сам.
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
учебный класс.
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);
}
);