Возможно, мой подход неверен, но я хотел бы изложить фактические требования перед моей попыткой разрешения. Мой подход основан на деталях, предоставленных hereNinject, чтобы вернуть имплантацию на основе перечислителя
Задача: в ориентированной на мастера структуре получить объект BaseWizardStepNavigator
на основе текущего шага. Например, если я на этапе WizardStep.Step1
, верните экземпляр Step1Navigator
. Экземпляр Step1Navigator
должен иметь любые впрыскиваемые сборки, поставляемые в его конструкторе, так что если у меня есть;
public class Step1Navigator : BaseWizardStepNavigator
{
private readonly ISomeReader _reader;
public Step1Navigator(ISomeReader reader)
: base(WizardSteps.Step1)
{
_reader = reader;
}
}
... что аргумент reader
заполняется соответствующей реализации.
Моя идея состоит в том, что у меня будет объект-менеджер, который ninject может создать, передав во всех реализациях базового класса (с соответствующими инъекциями IoC), что;
public class NavigatorManager
{
private readonly List<BaseWizardStepNavigator> _navigators;
public class NavigatorManager(IEnumerable<BaseWizardStepNavigator> navigators)
{
_navigators = new List<BaseWizardStepNavigator>(navigators);
}
public BaseWizardStepNavigator Get(WizardStep step)
{
return _navigators.FirstOrDefault(n => n.Step == step);
}
}
Там в конечном итоге будет 10-х шагов мастера с соответствующими навигаторов, чтобы определить, какой следующий шаг, но они должны ударить DB иногда, чтобы сделать это.
Моя текущая попытка и выполнение привязки в NinjectModule
, где я использую Ninject и Ninject.Conventions;
Модуль (способ загрузки);
Kernel.Bind(s => s.FromAssemblyContaining(typeof(BaseWizardStepNavigator))
.SelectAllClasses()
.WhichAreNotGeneric()
.InheritedFrom<BaseWizardStepNavigator>()
.BindWith<NavigatorBinding>());
var test = Kernel.GetAll<BaseWizardStepNavigator>();
Затем другие классы для привязок и поставщиков;
public class NavigatorBinding : IBindingGenerator
{
public IEnumerable<IBindingWhenInNamedWithOrOnSyntax<object>> CreateBindings(Type type, IBindingRoot bindingRoot)
{
if (type.IsInterface || type.IsAbstract)
{
yield break;
}
yield return bindingRoot.Bind(typeof(BaseWizardStepNavigator)).ToProvider<NavigatorProvider>();
}
}
public class NavigatorProvider : IProvider<BaseWizardStepNavigator>
{
public object Create(IContext context)
{
return null;
}
public Type Type { get { throw new NotImplementedException(); } }
}
Теперь, в то время как вызов kernel.GetAll<BaseWizardStepNavigator>()
действительно вызвать Provider
методы реализации, я немного потерял о том, как на самом деле заставить его выплюнуть обратно объекты. Документация неясна, и я не совсем уверен, что я даже на правильном пути. Помогите?
Даже если ваш менеджер получает список навигаторов в своем конструкторе, как он будет определять, какой из них следует возвращать на основе WizardStep? Мне кажется, что вам нужна карта какого-то типа между шагами и обработчиками. – JuanR
@ Juan есть, хотя я не включил его в пример выше. Конструктор 'BaseWizardStepNavigator' принимает аргумент' WizardStep', который должен указать каждый ребенок. В методе 'Get()' я смогу сделать 'if (manager.Step == step) return manager;'. Проблема заключается в реализации IProvider. Я не знаю, как заставить его выбирать и возвращать соответствующие объекты. – DiskJunky
Это было бы намного проще, если бы вы использовали интерфейсы вместо шагов для определения класса. Поскольку вы используете контейнер DI, просто создайте интерфейс для каждого шага и сопоставьте класс в контейнере. – JuanR