【发布时间】:2015-11-24 01:31:04
【问题描述】:
使用 C#、ASP.NET MVC 和 Autofac 之类的东西,我可以创建一个接口 IProductService 并将其绑定到一个具体的实现类 ProductService,代码如下(其中 builder 是 Autofac.ContainerBuilder):
builder.RegisterType<ProductService>().As<IProductService>();
然后在我的控制器中,我可以创建一个如下所示的构造函数:
using System.Web.Mvc;
namespace SomeNamespace
{
public class HomeController : Controller
{
private IProductService _productService;
public HomeController(IProductService productService)
{
this._productService = productService;
}
}
}
使用反射,Autofac 能够确定我希望将IProductService 实现注入到我的构造函数中,并提供我之前注册的类型作为具体实现类型,并根据需要解决ProductService 类中的依赖关系创建一个实例供控制器使用。
我想使用 Symfony 实现类似的目标。我目前的理解是,我可以通过以下方式使用 Symfony 的服务:
services:
product_repository:
class: App\WebBundle\Repository\ProductRepository
product_service:
class: App\WebBundle\Service\ProductService
arguments: ["@product_repository"]
home_controller:
class: App\WebBundle\Controller\HomeController
arguments: ["@product_service"]
然后使用这样的控制器:
namespace App\WebBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
public class HomeController extends Controller {
private $productService;
public function __construct(IProductService $productService) {
$this->productService = $productService;
}
}
这可行,但远非理想,因为我现在不仅在构造函数中提供接口类型提示(这已经明确了我要注入的服务),我还必须弄清楚服务名称并提供它们在我想要使用服务的每个类的配置文件中。
我可以看到的另一种选择是利用Symfony\Bundle\FrameworkBundle\Controller\Controller 上的get 函数,如下所示:
namespace App\WebBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
public class HomeController extends Controller {
private $productService;
public function __construct() {
$this->productService = $this->get("product_service");
}
}
这种方法有效,除了我现在完全依赖 Symfony 的服务容器(将来很难迁移到另一个框架),我的 IDE 不知道 $this->productService 是什么类型,所以我也失去了自动完成功能。其他开发者也不清楚该服务来自哪里,我必须反复参考配置文件以找出哪个类注册了“product_service”的id(我无法使用我的IDE的导航工具跳转到接口的声明或查找所有实现该接口的类。
我的理解是 Laravel 的 Illuminate Container 组件提供了我想要实现的功能(使用反射来确定构造函数/方法中暗示的类型,并使用开发人员提供的绑定解决依赖关系)但我不确定是否可以使用 Symfony 轻松设置。有什么方法可以在使用 Symfony 的同时实现这个功能(也许我可以听 kernel.controller 并在那里做一些事情)?
【问题讨论】:
-
JMSDIExtraBundle 可能对你有用.. jmsyst.com/bundles/JMSDiExtraBundle/master/usage
-
@Qoop 感谢您的链接。这个包很有趣,使用注释而不是在配置文件中配置东西可能更明显。遗憾的是,PHP 中的类元数据/注释没有适当的语言支持,因为我不太喜欢当前的方法(使用 doblock cmets)。虽然捆绑似乎有助于使服务注册更加明显,但它似乎不允许接口 => 迄今为止我读过的文档中的类绑定,这是我想做的最重要的事情。
标签: php symfony dependency-injection