Ninject для возврата имплентации на основе перечислителя
Вполне возможно, что мой подход неверен, но я бы хотел изложить фактические требования, прежде чем пытаться решить. Мой подход основан на деталях, представленных здесь
Задача: в волшебно-ориентированной структуре получить 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 шагов мастера с соответствующими навигаторами, чтобы определить следующий шаг, но для этого им потребуется время от времени попадать в БД.
Моя текущая попытка и выполнение привязки в 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
методы реализации, я немного растерялся относительно того, как заставить его выплевывать объекты. Документация неясна, и я не совсем уверен, что даже на правильном пути. Помогите?
1 ответ
Мне удалось заставить реализацию работать довольно просто в конце. Там не было никакой необходимости IBindingGenerator
или же IProvider
Реализации.
Код для Step1Navigator
а также NavigatorManager
остается такой же.
NinjectModule
код привязки изменяется на;
// set the navigator bindings
Kernel.Bind(s => s.FromAssemblyContaining(typeof(BaseWizardStepNavigator))
.SelectAllClasses()
.WhichAreNotGeneric()
.InheritedFrom<BaseWizardStepNavigator>()
.BindAllBaseClasses()
.Configure(c => c.InRequestScope())
);
// pass in all children of BaseWizardStepNavigator to the manager instance
Bind<NavigatorManager>().ToSelf()
.InRequestScope()
.WithConstructorArgument(typeof(IEnumerable<BaseWizardStepNavigator>),
n => n.Kernel.GetAll<BaseWizardStepNavigator>());
.InRequestScope()
специфично для веб-приложений. Измените соответствующим образом, если вы используете это в своем собственном коде для .InSingletonScope()
, так далее.