Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Dependency injection DI容器:从相同类型的集合中注入正确的组件?_Dependency Injection_Ioc Container_Ambiguity - Fatal编程技术网

Dependency injection DI容器:从相同类型的集合中注入正确的组件?

Dependency injection DI容器:从相同类型的集合中注入正确的组件?,dependency-injection,ioc-container,ambiguity,Dependency Injection,Ioc Container,Ambiguity,我正试图在PHP中基于构造函数注入攻击我自己的依赖注入容器。容器实例化复杂对象,并根据构造函数中使用反射的类型提示,向它们注入所需的对象 我显然偶然发现的一件事是,我可以注册多个可以注入的相同类型的组件(扩展相同的类/实现相同的接口)。例如,如果两个对象都需要实现迭代器接口的不同对象,该怎么办。DI容器通常如何处理这个问题?如何让容器决定哪些接口不明确的对象需要注入到哪些复杂对象中 或者单个DI容器只负责创建一种类型的复杂对象?换句话说:为每个复杂对象实例化一个不同的DI容器。我很难想象这就是目

我正试图在PHP中基于构造函数注入攻击我自己的依赖注入容器。容器实例化复杂对象,并根据构造函数中使用反射的类型提示,向它们注入所需的对象

我显然偶然发现的一件事是,我可以注册多个可以注入的相同类型的组件(扩展相同的类/实现相同的接口)。例如,如果两个对象都需要实现迭代器接口的不同对象,该怎么办。DI容器通常如何处理这个问题?如何让容器决定哪些接口不明确的对象需要注入到哪些复杂对象中


或者单个DI容器只负责创建一种类型的复杂对象?换句话说:为每个复杂对象实例化一个不同的DI容器。我很难想象这就是目的,对吗?

你描述的不是DI本身,而是自动布线,比普通DI更进一步。通常,使用DI,您可以显式配置哪些组件连接到哪些组件

Autowired DI只适用于粗粒度组件,其中给定类型只有一个合理的实现(例如DAOs)。在类型不明确的情况下,您可以将其中一个标记为“主要”,或者将其他标记为“非候选”,或者使用所需组件的名称显式标记依赖项


如果有帮助的话,您可以阅读Spring如何处理自动布线和

根据您的问题的意思,以下是Guice(Java的DI框架)使用的内容:

如果每次有
Foo
的注入请求时,您只是想要一个不同的对象,那么在连接应用程序时,不要将
Foo.class
绑定到
Foo
的特定实例,而是绑定一个
提供者
,后者是一个按需创建
Foo
的对象。然后,注入
Foo
的每个地方都会得到一个新实例。如果您只是将
Foo
绑定到一个类,而不是一个
Foo
实例(比如,
Foo
是一个接口,您将它绑定到实现
Foo
的类
RealFoo.class
),您也会得到同样的效果-每次都会创建一个新实例。(这是默认的“unscoped”行为。Guice作用域的行为超出了此注释的范围)

但是,如果您需要在连接应用程序时构造两个
Foo
实例,然后能够说“此Foo实例在制作
Bar
Baz
时使用,而另一个实例在制作
Bumble
时使用”,您要做的是注释注入点,然后在连接应用程序时说:

Foo foo1 = new Foo("1");
Foo foo2 = new Foo("2");
bind(Foo.class).annotatedWith(Names.named("Bar")).toInstance(foo1);
bind(Foo.class).annotatedWith(Names.named("Baz")).toInstance(foo1);
bind(Foo.class).annotatedWith(Names.named("Bumble")).toInstance(foo2);
public Bar(@Named("Bar") Foo foo) { ...
在这里,我假设您已经用如下内容注释了
Bar
的构造函数的参数:

Foo foo1 = new Foo("1");
Foo foo2 = new Foo("2");
bind(Foo.class).annotatedWith(Names.named("Bar")).toInstance(foo1);
bind(Foo.class).annotatedWith(Names.named("Baz")).toInstance(foo1);
bind(Foo.class).annotatedWith(Names.named("Bumble")).toInstance(foo2);
public Bar(@Named("Bar") Foo foo) { ...
同样,对于
Baz
Bumble
。当然,如果用相同的东西注释
Bar
Baz
的构造函数,可以跳过
bind
行之一


我知道有基于反射的php注释处理框架,或者您可以使用基于参数名称的约定。

Skaffman,感谢您的澄清。我不知道这叫做自动布线。但这听起来很合理。我想我应该支持你上次提出的方案,因为从长远来看,其他方案可能会造成不期望的影响。我正在尽我所能使它成为防弹的。回到绘图板。:)你可能是对的。但我通常想自己玩一玩这些东西(只是为了在以后求助于现有的解决方案,哈哈;-),以帮助我更好地理解它所包含的内容。此外,我还想提高我的OOP技能,并像这样进行练习。:)顺便说一句,感谢您提供的额外资料。第一部分给出了您提供的选项以及我从中得出的结论,如果存在无法解决的歧义,我需要抛出一个异常。我删除了标记“php”,因为选择的实现语言与问题并不相关。O,这是一个比我想象的更复杂的实现。我甚至不担心相同的对象被不同的注入实例化(我还没有想到)。相反,我指的是不同的对象,它们都需要注入相同基类型或基接口的对象,但实际上是不同的类。(请原谅我把这里的正确术语弄错了)。但是你的例子把事情放在一个完全不同的角度。优点:)顺便说一句,我不确定我是否喜欢注释选项。我希望尽可能保持它的“干净”,而不必改变主题。如果你明白我的意思的话,它应该可以在架子上放置任何物品。构造函数参数名称,或者更好,在DI配置中显式地命名依赖项可能是一种方法。