我很奇怪,为什么净IoC容器不要轻易支持多个实现了单接口! 也许是我错了,但据我所看到的,像Ninject框架部分支持使用注释功能( 如何? )。 我不认为像温莎或简单的注射器其他框架有一个简单的机制来支持此方案。
是否有这是为什么不通过许多框架支持的任何原因? 据我所知,对使用界面的最重要原因之一就是实现松耦合。 如果框架旨在提高松耦合,不流畅支持多种实现单一接口,我不明白为什么!
PS我当然明白,会有在运行时的分辨率问题,容器会混淆选择哪种实现,但是那是后话,其已在设计中考虑,对不对?
我很奇怪,为什么净IoC容器不要轻易支持多个实现了单接口! 也许是我错了,但据我所看到的,像Ninject框架部分支持使用注释功能( 如何? )。 我不认为像温莎或简单的注射器其他框架有一个简单的机制来支持此方案。
是否有这是为什么不通过许多框架支持的任何原因? 据我所知,对使用界面的最重要原因之一就是实现松耦合。 如果框架旨在提高松耦合,不流畅支持多种实现单一接口,我不明白为什么!
PS我当然明白,会有在运行时的分辨率问题,容器会混淆选择哪种实现,但是那是后话,其已在设计中考虑,对不对?
团结具有相同的功能
注册一个名为依赖
var container = new UnityContainer();
container.RegisterType<IConnector, Connector>("TestConnector");
通过名称解析
container.Resolve<IConnector>("TestConnector");
同样的方法
[Dependency("TestConnector")]
public IConnector Connector { get; set; }
温莎具有相同
class Program
{
static void Main(string[] args)
{
var container = new WindsorContainer()
.Register(Component.For<IConnector>().ImplementedBy<ConnectorA>().Named("ConnectorA"))
.Register(Component.For<IConnector>().ImplementedBy<ConnectorB>().Named("ConnectorB"));
var connectorA = container.Resolve<IConnector>("ConnectorA");
Console.WriteLine("Connector type: {0}", connectorA.GetType());
var connectorB = container.Resolve<IConnector>("ConnectorB");
Console.WriteLine("Connector type: {0}", connectorB.GetType());
Console.ReadKey();
}
}
public interface IConnector
{
}
public class ConnectorA : IConnector
{
}
public class ConnectorB : IConnector
{
}
我建议看看约定优于配置和尤其是基于公约依赖注入和基于上下文的依赖注入。 大多数的IoC如果不是全部支持这两种方法。 你可以找到不同的IoC库,当几个执行绑定到一个接口,以及如何有用它可能是许多有趣的样本。
例如ninject并支持多种实现一个接口的结合:依赖于上下文或属性,按名称,所以一个 。
下面的代码片段结合上implemetation取决于automaticaly目标类型:
Bind<IWarrior>().To<Samurai>().WhenInjectedInto(typeof(OnLandAttack));
Bind<IWarrior>().To<SpecialNinja>().WhenInjectedInto(typeof(AmphibiousAttack));
当你的配置是在XML或数据库非常有帮助。 考虑到InNamedScope
也:
Bind<IWeapon>().To<Shuriken>().Named("Strong");
Bind<IWeapon>().To<Dagger>().Named("Weak");
随着你的项目的不同部分的不同依赖配置。
你的前提是错误的。
温莎很愉快地接受同一服务的多种实现的注册。 除了由GSerjo提到的命名组件分辨率支持,在温莎(默认),第一个注册的实施将赢得胜利,但你可以通过使用覆盖此IsDefault()
注册一个替代实现方法时。 请参阅http://docs.castleproject.org/Windsor.Registering-components-one-by-one.ashx了解更多详情。
如果您想在选择从多个实现多运动的控制,你可以创建一个IHandlerSelector实现这样做。 请参阅http://stw.castleproject.org/Windsor.Handler-Selectors.ashx了解更多详情。
我的容器Griffin.Container支持它。
registrar.RegisterConcrete<OneImplementation>();
registrar.RegisterConcrete<AnotherImplementation>();
并获取:
var services = container.Resolve<ITheService>();
但是,你不能让一个具体的实施。 这是一个设计决策。 这是更好的在容器中注册一个工厂如果要得到具体实施。 阅读更多这里的最佳实践部分。
Griffin.Container可以在github上找到: https://github.com/jgauffin/griffin.container
StructureMap提供这些能力:
For<IMyInterface>().Add<MyInterfaceImpl1>().Named("MyInterfaceImpl1");
For<IUsingInterface>().Add<UsingInterfaceImpl>().Ctor<IMyInterface>().Is(i => i.GetInstance<IMyInterface>("MyInterfaceImpl1"));
你的问题是有点模糊,因为你不提供,当你认为你需要这样的一个具体的例子。 在大多数情况下,你的应用程序或设计有问题,或者你没有关注DI最佳实践。
所有容器允许您使用相同的接口作为注册多个依赖IEnumerable<ThatInterface>
即使他们没有为多个实例的深度支持。 注射服务的列表到然而等服务,是一家集设计气味,倒不如躲在一个复合这份名单。 这隐藏了一个事实,有抽象的背后多种实现,并让您轻松改变这些多重实现的使用方式,通过在应用程序只改变一个地方。 我不相信任何IoC框架具有产生复合材料为你的任何支持,因为没有处理包裹的实现没有一个默认的方式。 你必须写自己的组合。 但是,由于编写这样的复合材料是真的,真的很简单,这证明没有在框架这样的功能。
如果你想有多个实现,但总是需要一个要返回,根据一些配置,总有办法做到这一点。 大多数容器允许你在一个XML配置文件来配置这些依赖关系。 但是,即使在容器中不包含这种功能,手动读取配置文件中的这个值和登记在容器中的正确类型是很容易的。
如果你有一个实现一定的接口,用于生产和单元测试的目的另一个实现的,你应该只登记在容器中的生产实施。 单元测试应该清楚任何DI容器,而应手动测试创建一个类,并在它的构造函数注入假的依赖关系,通过简单的new
ING的类型了。 使用DI容器,污染和你的测试变得复杂。 为了顺利完成这件事,你将需要设计构造注塑模式围绕着这样的类型。 不要调用服务中的容器(或任何其他的门面在容器)测试,以获取依赖。