【发布时间】:2012-02-28 20:26:19
【问题描述】:
这个问题与 Symfony 2 没有严格的关系,但由于我使用 Symfony 2 组件并且以后可能会使用 Symfony\Component\DependencyInjection\Container 作为 DI-Container,所以它可能是相关的。
我目前正在使用 Symfony 2 中的组件构建一个小型库,例如HttpFoundation,验证器,Yaml。 My Domain Services 都在扩展一个基本的 AbstractService,只提供 Doctrine\ORM\EntityManager 和 Symfony\Component\Validator\Validator 通过构造函数注入,如下所示:
abstract class AbstractService
{
protected $em;
protected $validator;
/**
* @param Doctrine\ORM\EntityManager $em
* @param Symfony\Component\Validator\Validator $validator
*/
public function __construct(EntityManager $em, Validator $validator)
{
$this->em = $em;
$this->validator = $validator;
}
}
扩展此 AbstractService 的服务类现在可能需要注入附加组件,例如 Symfony\Component\HttpFoundation\Session。至于我这样做:
class MyService extends AbstractService
{
/**
* @var Symfony\Component\HttpFoundation\Session
*/
protected $session;
/**
* @param Symfony\Component\HttpFoundation\Session $session
* @param Doctrine\ORM\EntityManager $em
* @param Symfony\Component\Validator\Validator $validator
*/
public function __construct(Session $session, EntityManager $em, Validator $validator)
{
parent::__construct($em, $validator);
$this->session = $session;
}
}
有没有更优雅的方法来解决这个问题,而不必重申父级的构造函数参数,例如改为使用 Setter-Injection for Session?
正如我所看到的,当我对 Session 使用 Setter-Injection 时,我必须在我的方法中访问它之前添加检查,它是否已经被注入,这是我想要避免的。另一方面,我不想“重复”注入所有服务共享的基本组件。
【问题讨论】:
-
(旁注) 您应该保持子类中参数的顺序与超类型中的顺序相同。
-
@Gordon 你的意思是 Session 应该追加而不是前置?你能解释一下为什么吗?在前面添加“新信息”对我来说似乎更自然。
-
子类型是超类型的特化。您可以像超类型一样创建它,但带有一个附加参数,因此将它放在最后更自然,因为它只会添加到超类型的 ctor 签名中,而不是完全更改它。它提供了一个更可预测的 API。
-
@Gordon 这是我一直觉得奇怪的事情,如果您有两个具有默认值的参数,但您想添加 没有 的第三个参数一个默认值......放置它的逻辑位置是在其他两个之前
-
好的!现在我明白他们为什么制作 Laravel
标签: php oop dependency-injection symfony