是否可以将某些服务放入另一个容器中,该容器将缩小到特定的服务集?或者将某些特定服务分离到某种子容器?我问这个问题是因为我需要将一组服务注入到另一个服务中,并且我认为将整个容器投入服务是个坏主意。当然,我可以在服务类中为我想要注入的所有服务创建一个属性,但这是我试图避免的解决方案。
我将不胜感激任何帮助,如果您需要有关此问题的更多信息,请询问。
答案 0 :(得分:1)
基本上,您可以通过使用特殊名称“标记”某些服务来使用DIC 为此,您需要将服务定义到一个文件中(遵循DIC规范)并以特定方式标记它们(在这种情况下,代码将由Sonata Admin Bundle采用,用于解释)
# MyBundle/Resources/config/admin.yml
services:
sonata.admin.tag:
class: YourNS\AdminBundle\Admin\BlogAdmin
tags:
- { name: sonata.admin, manager_type: orm, group: posts, label: "Blog" }
arguments:
- ~
- YourNS\AdminBundle\Entity\Course
- 'SonataAdminBundle:CRUD'
calls:
- [ setTranslationDomain, [YourNSAdminBundle]]
在这种情况下,我正在定义一个名为sonata.admin.tag
的服务,该服务标有sonata.admin
标记。
我可以定义其中的十几个,所有这些都带有sonata.admin.tag
标记名称。
一旦我完成了这个,我必须创建一个“特殊”文件(我将放入捆绑的DependencyInjection
文件夹[for convention]),这是CompilerPass
file。
什么是CompilerPass文件?
编译器通行证让您有机会操纵其他服务 已在服务容器中注册的定义。[...] 编译器通过的最常见用例之一是使用 标记服务(阅读有关组件部分中标记的更多信息 “使用标记服务”)。
这正是你所需要的!
现在您必须搜索(在此文件中)标记为(在此特定示例中)sonata.admin
class AddDependencyCallsCompilerPass implements CompilerPassInterface
{
/**
* {@inheritDoc}
*/
public function process(ContainerBuilder $container)
{
$groupDefaults = $admins = $classes = array();
$pool = $container->getDefinition('sonata.admin.pool');
foreach ($container->findTaggedServiceIds('sonata.admin') as $id => $tags) {
foreach ($tags as $attributes) {
$definition = $container->getDefinition($id);
$arguments = $definition->getArguments();
if (strlen($arguments[0]) == 0) {
$definition->replaceArgument(0, $id);
}
if (strlen($arguments[2]) == 0) {
$definition->replaceArgument(2, 'SonataAdminBundle:CRUD');
}
$this->applyConfigurationFromAttribute($definition, $attributes);
$this->applyDefaults($container, $id, $attributes);
$arguments = $definition->getArguments();
$admins[] = $id;
//other logic here
$pool->addMethodCall('setAdminClasses', array($classes));
正如您在此处所见,我们正在搜索使用sonata.admin
($container->findTaggedServiceIds('sonata.admin')
)标记的服务,我们将这些服务(在这种情况下,特定于奏鸣曲管理包)添加到{{1这是一个$pool
现在,我们必须将一个CompilerPass注册到我们的bundle文件中(你在注册bundle到应用程序之前创建的那个)
ContainerBuilder
现在,您已经为此捆绑包注册了某种服务。
更专注于服务工厂Symfony2的Service Container提供了一种强大的控制方式 对象的创建,允许您指定传递给的参数 构造函数以及调用方法和设置参数。 但是,有时候,这并不能为您提供所需的一切 构建你的对象。
或者更像是服务实例化的“入口点”。
答案 1 :(得分:0)
出于性能和可测试性的原因,确实没有建议注入整个容器。
如果所有依赖项的构造函数或getter / setter注入不是您想要的方式...
... Service Factory是您正在寻找的。 p>
通过这种方式,您可以构建一个包含其他服务的服务,并仅注入此服务。
那就是你所说的“子容器”。