到目前为止,我已经设法使用Unity和Castle Windsor轻松实现上下文绑定。意思是,给定一个接口的多个注册实现,我可以注册使用客户端组件作为依赖来选择特定组件的客户端组件。但是对于Ninject,执行此操作和我在以下示例中发现的界面似乎并不相同:
团结示例:
给出接口,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");
温莎城堡示例:
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>();
注入(使用绑定元数据):
class FooClient{
public FooClient(Named["Foo2"] IFoo fooDependency)
{
}
....
}
通过直接使用服务定位器而不是依靠自动解析来要求特定的实现,甚至在文档中也承认是一种反模式。
Unity&Castle Windsor完全按预期工作,fooClient使用了IFoo的Foo2实现。它已自动解决。
关于Ninject方法,这种方法行得通,但这意味着它很难融入更高级别组件的实现中,而且我违反了依赖反转原则。关于Unity / Windsor方法的一个好地方是组成根(IOC设置)是隔离点。
我错过了Ninject API上的某些东西,可以保留DIP吗?
答案 0 :(得分:0)
您可以使用:
Bind<FooClient>().ToSelf();
Bind<IFoo>().To<Foo2>().WhenInjectedInto<FooClient>();
Bind<Foo2>().ToSelf();
Bind<FooClient>().ToSelf()
.WithConstructorArgument(typeof(IFoo)), ctx => ctx.Kernel.Get<Foo2>());
注意:当然,您也可以解决Kernel.Get<IFoo>("foo2")
。
注意:键入“来自内存”,可能无法编译,因为语法可能略有不同。