短版本
有时我看到一段代码,其中将依赖项注入到控制器的构造函数中,但是它提供了什么好处?
长期版本
让我们假设您正在看到类似以下代码的代码。
//ASP.NET
public class SampleController : Controller
{
private IDependency dependency;
public SampleController(IDependency dependency)
{
this.dependency = dependency;
}
}
或者,如果您更喜欢PHP,那么让我们看一下下面的
//PHP with Laravel
namespace App\Http\Controllers;
class SampleController extends Controller
{
private $dependency;
public function __construct(Dependency $dependency)
{
$this->dependency = $dependency;
}
}
据我所知,依赖注入旨在 使客户端与其依赖项脱钩 ,以便...
...等等。
但是,控制器没有实例化,
$service = new Service();
$controller = new Controller($service);
//you don't do such a thing, do you?
....(通常)控制器也不使用setter函数。
尽管如此,我仍然在互联网上看到这种方法,包括ASP.NET's doc。
将依赖项注入控制器而不是使用new
关键字在构造函数中实例化类真的有好处吗? (如果是这样,这种方法如何改善您的代码?)
答案 0 :(得分:1)
好吧
因此,在使用DI时,通常是将接口注入到控制器中吗?
如果您要换出执行该怎么办?
例如,您有一个ISearchApi
,当前您已在自己的DI代码中将其设置为ISearchApi
的实现为GoogleApi
,现在您想将其交换为BingApi
。您无需触摸任何现有代码,因为所有代码都在接口后面被抽象了。这是Dependency Inversion Principle的一部分。
如果BingApi
的实现还期望构造函数中有另一个类怎么办?并且该类还期望在其构造函数中有更多这样的类:
new BingApi(new BingControls(new Api(new HttpClient, "ApiKey")));
这将很难维持,如果在您的DI容器中正确设置了它,那么您就不必为此担心。
另一个原因是进行单元测试。我将不讨论控制器在逻辑方面应该做什么。但是,对期望有具体实现的控制器进行单元测试会更加困难,特别是如果该实现调用任何服务/数据库。由于控制器只是new
对其进行模拟,因此无法模拟。
我能看到的依赖注入的唯一缺点是,在应用程序启动时还有更多的代码要写。但是考虑到所提供的好处,这是非常小的。