До сих пор мне удалось легко реализовать контекстную привязку с использованием Unity и Castle Windsor.То есть, учитывая несколько зарегистрированных реализаций интерфейса, я могу зарегистрировать клиентский компонент, который использует их в качестве зависимости для выбора конкретной.Однако в Ninject, похоже, нет такого интерфейса для выполнения этого, и пример, который я нашел на:
https://github.com/ninject/Ninject/wiki/Contextual-Binding#simple-constrained-resolution-named-bindings
Пример Unity:
Данный интерфейс, IFoo и реализации Foo1, Foo2, Foo3.
container.RegisterType<IFoo , Foo1>("Foo1", new TransientLifetimeManager());
container.RegisterType<IFoo , Foo2>("Foo2", new TransientLifetimeManager());
container.RegisterType<IFoo , Foo3>("Foo3", new TransientLifetimeManager());
container.RegisterType<FooClient, FooClient>("FooClient1", new InjectionConstructor(new ResolvedParameter<IFoo>("Foo2")));
var fooClient = container.Resolve<FooClient>("FooClient1");
Пример Castle Windsor:
internal class FooInstaller: IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Component.For<IFoo>().Named("Foo1").ImplementedBy<Foo1>().LifeStyle.Transient);
container.Register(Component.For<IFoo>().Named("Foo2").ImplementedBy<Foo2>().LifeStyle.Transient);
container.Register(Component.For<IFoo>().Named("Foo3").ImplementedBy<Foo3>().LifeStyle.Transient);
container.Register(Component.For<FooClient>().LifeStyle.Singleton.DependsOn(ServiceOverride.ForKey<IFoo>().Eq("Foo2")));
}
}
var fooClient = container.Resolve<FooClient>();
Ninject (используяметаданные привязки):
class FooClient{
public FooClient(Named["Foo2"] IFoo fooDependency)
{
}
....
}
даже признается в документации как анти-шаблон, напрямую используя сервисный локатор для запроса конкретной реализации вместо того, чтобы полагаться на автоматическое разрешение.
Unity & Castle Windsor работал точно так, как ожидалось, fooClient использовал Foo2-реализацию IFoo.Он был автоматически разрешен.
Что касается подхода Ninject, он сработал, но это означает, что он запутан в реализации компонента более высокого уровня, и я нарушил принцип инверсии зависимостей.Хорошая часть подхода Unity / Windsor - корень композиции (настройка IOC) - это точка изоляции.
Есть ли в Ninject API что-то, что я пропустил, что позволило бы мне сохранить DIP?