АвтоФак с свободностью в MVC2
-
29-09-2019 - |
Вопрос
Я получаю «не зарегистрированную ошибку» во время выполнения в вызове ValidatorFactory.createInstance. Похоже, тип отправляется в метод правильный.
Мой регистрационный код:
...
builder.RegisterAssemblyTypes(assembly).Where(t => t.Name.EndsWith("Validator")).As<IValidator>();
builder.Register(d => _containerProvider).As<IContainerProvider>();
builder.Register(d => new ValidatorFactory(_containerProvider.ApplicationContainer.Resolve<IContainerProvider>())).As<IValidatorFactory>();
_containerProvider = new ContainerProvider(builder.Build());
Мой кормиорный процесс:
public class ValidatorFactory : ValidatorFactoryBase {
private readonly IContainerProvider _containerProvider;
public ValidatorFactory(IContainerProvider containerProvider) {
_containerProvider = containerProvider;
}
public override IValidator CreateInstance(Type validatorType) {
return _containerProvider.ApplicationContainer.Resolve<IValidator>(validatorType);
}
}
Мой вид моделей и код валидатора:
[Validator(typeof(EmployeeViewModelValidator))]
public class EmployeeViewModel {
public EmployeeViewModel() {}
public EmployeeViewModel(string firstName) {
FirstName = firstName;
}
public string FirstName { get; private set; }
}
public class EmployeeViewModelValidator : AbstractValidator<EmployeeViewModel> {
public EmployeeViewModelValidator() {
RuleFor(x => x.FirstName)
.NotEmpty();
}
}
Мое лучшее предположение - это то, что я зарегистрируюсь неправомерно.
Решение 3
Текущий регистрационный код:
builder.RegisterType<EmployeeViewModelValidator>().Keyed<IValidator>(typeof(EmployeeViewModel));
builder.RegisterType<ValidatorFactory>().As<IValidatorFactory>();
_containerProvider = new ContainerProvider(builder.Build());
Текущий вариаторФство:
public class ValidatorFactory : ValidatorFactoryBase {
readonly IIndex<Type, IValidator> _validators;
public ValidatorFactory(IIndex<Type, IValidator> validators) {
_validators = validators;
}
public override IValidator CreateInstance(Type validatorType) {
return _validators[validatorType];
}
}
Та же ошибка внутри CreateInStance:
Запрашиваемая услуга «FreentValidation.ivaliDator» [.employeeviewModel] (FreentValidation.ivalidator) 'не зарегистрирована.
Другие советы
Разрешить из нескольких классов, которые реализуют IValidator
, то Autofac Документация показывает пару методик. Я не думаю, что вы можете использовать сканирование сборки с этими методами; Вы будете зарегистрировать валидаторы индивидуально.
По имени
builder.RegisterType<EmployeeViewModelValidator>().Named<IValidator>("employee");
var r = container.Resolve<IValidator>("employee");
По ключу
Документация показывает перечисление, используемое в качестве ключа, но вы можете использовать тип в качестве ключа, который позволил бы вам позвонить Resolve
используя validatorType
быть переданным вам в CreateInstance
метод.
builder.RegisterType<EmployeeViewModelValidator>().Keyed<IValidator>(typeof(EmployeeViewModelValidator));
var r = container.Resolve<IValidator>(validatorType);
Примечание. Документация предназначена для версии 2.3 AUTOFAC. Я использую 2.2.4, поэтому имена методов выше варьируются от документации.
Надеюсь это поможет.
Другой ответ @adrift - хороший чистый подход. Просто добавить несколько заметок, это также работает с IIndex<K,V>
Тип отношений, который Autofac обеспечивает автоматически, например:
public class ValidatorFactory : ValidatorFactoryBase {
readonly IIndex<Type, IValidator> _validators;
public ValidatorFactory(IIndex<Type, IValidator> validators) {
_validators = validators;
}
public override IValidator CreateInstance(Type validatorType) {
return _validators[validatorType];
}
}
Важная заметка: не используйте IContainerProvider
и ApplicationContainer
в компоненте - вместо этого использовать IComponentContext
или IIndex<K,V>
как указано выше. Это поможет предотвратить пожизненные вопросы (ваш пример ассоциирует валидаторы с приложением, а не с течением времени запроса.)