到目前为止,我已经设法使用Unity和Castle Windsor轻松实现上下文绑定。意思是,给定多个注册的接口实现,我可以注册使用那些作为依赖项的客户端组件来选择特定的接口。但是对于Ninject,似乎没有相同的界面来执行此操作以及我在上面找到的示例:
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");
温莎城堡的例子:
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使用了IFoo的Foo2实现。它自动解决了。
关于Ninject方法,这是有效的,但这意味着它很难实现更高级别的组件,我违反了依赖倒置原则。关于Unity / Windsor方法的好处是组合根(IOC设置)是隔离点。
我错过了Ninject API上的某些内容可以让我保留DIP吗?
您可以使用:
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")
。注意:键入“from memory”,可能无法编译,因为语法可能略有不同。