如何将服务的方法结果作为另一个服务的参数注入?

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 容器对象的性能明显更高。

以上是关于如何将服务的方法结果作为另一个服务的参数注入?的主要内容,如果未能解决你的问题,请参考以下文章

Web 服务 URL 中的 SQL 注入作为参数值

.net core 3 依赖注入服务作为“配置”的参数

sql中引用一个表的查询结果作为条件来查询另一个表如何实现?

如何将 UserManager 注入 ASP.NET Core 2.0 中的另一个服务

在 Angular 2(Beta)中将一项服务注入另一项服务的最佳方法是啥?

JQM 如何增强动态注入的整页内容(作为重定向的结果)?