如何将服务的方法结果作为另一个服务的参数注入?
Posted
技术标签:
【中文标题】如何将服务的方法结果作为另一个服务的参数注入?【英文标题】:How to inject method result of a service as an argument for another service? 【发布时间】:2016-03-16 08:54:10 【问题描述】:我有一个 FooService
从另一个配置服务获取一些数据。
我有该配置服务,因为配置因请求数据而异。配置服务注入了RequestStack
并构建了相关的配置数组。
我的FooService
如下所示:
class Foo
private $config;
/**
* @param Config $config
*/
public function __construct(Config $config)
$this->config = $config->getData();
然而,我宁愿只注入getData
的方法调用结果,而不是注入服务,因为它更容易进行单元测试。我不需要模拟配置,我可以传递一个数组。
我当前的service.yml
的定义如下:
config:
...
foo:
class: Kopernikus\LeBundle\Service\Foo
arguments:
- @config
我尝试通过以下方式更改我的 foo
定义,例如工厂方法:
foo:
class: Kopernikus\LeBundle\Service\Foo
arguments:
- [@config, getData]
但这也注入了整个服务。
【问题讨论】:
【参考方案1】:您可以使用表达式语言 (New in Symfony 2.4) 实现此目的
如文档here 中所述,您可以执行以下操作:
config:
...
foo:
class: Kopernikus\LeBundle\Service\Foo
arguments: ["@=service('config').getData()"]
希望有帮助
【讨论】:
这里的括号太多了,因为它们注入了一个数组的数组。只需"@=service('config').getData()"
就足够了。 =)
自版本 3 起已移动 here【参考方案2】:
您基本上是在要求一个依赖注入容器。您可以自己制作一个具有简单函数(例如)get()
的函数,该函数返回 Foo
的新实例?您可以将其定义为在每次调用 get()
时创建新对象,或者创建更多始终返回相同对象的单例(通过将其存储在私有静态变量中)。
例如,
<?php
class FooContainer implements YourContainerInterface
public static function get()
// Config logic here
return new Foo($config);
【讨论】:
听起来 OP 正在询问如何将方法调用的结果注入服务而不是服务本身——尽管我不清楚他们为什么要这样做,所以我可能是误解了问题。 @JeremyHarris 我已经更新了我为什么要这样做的用例。 以这种方式传递函数的唯一方法是通过字符串,这实际上并不理想,因为您无法对其进行任何类型检查(不使用其他逻辑)。在 PHP 中执行此操作的适当方法是通过容器对象。 我看不到这个 esp 的好处。与其他两个提供的答案相比。我也不明白为什么不能进行类型检查。 config 函数当前在依赖服务的构造函数中返回一个数组,我可以使用该类型提示(或者如果我更改为一个对象,请使用它的类类型提示)。您能否详细说明这种方法何时会带来好处?或者与其他答案相比,我没有看到什么好处? 如果您有一个需要 DI 容器的类,以便它可以访问服务,您可以根据该特定 DI 容器或其父类/接口进行类型提示。其他示例使用各种形式的 PHP 魔法,将字符串用作参数,然后解析字符串并返回一个对象。这是浪费和缓慢的。传递返回服务的 DI 容器对象的性能明显更高。以上是关于如何将服务的方法结果作为另一个服务的参数注入?的主要内容,如果未能解决你的问题,请参考以下文章
sql中引用一个表的查询结果作为条件来查询另一个表如何实现?
如何将 UserManager 注入 ASP.NET Core 2.0 中的另一个服务