4

在我在网上看到的大多数示例中,MVC 控制器中的 DI 都是这样完成的

public ProductController(IProductRepository Rep)
{
    this._rep = Rep;
}

使用了自定义 ControllerFactory,它利用了选择的 DI 框架并注入了存储库。

为什么以上认为优于

public ProuctController()
{
    this._rep = ObjectFactory.GetInstance<IProductRepository>();
}

这将获得相同的结果,但不需要自定义控制器工厂。

就测试而言,Test App 可以有一个单独的 BootStrapper。这样,当控制器被测试时,他们可以得到假的存储库,当它们被真正使用时,他们会得到真正的存储库。

4

3 回答 3

5

第二个构造函数的主要缺点是现在必须为每个测试正确配置 IoC 容器。随着代码库的增长和测试场景的多样化,这种设置可能会成为真正的负担。当您明确地通过测试替身时,测试通常更易于阅读和维护。

另一个问题是将大量类耦合到特定的 DI/IoC 框架。当然,有一些方法可以将其抽象出来,但是您仍然在整个类中散布代码来检索依赖项。由于所有好的框架都可以通过查看构造函数来确定您需要哪些依赖项,因此这是浪费大量精力和重复代码。

于 2009-06-25T15:14:37.673 回答
5

构造函数注入(第一种方法)优于服务定位器模式(第二种方法)有几个原因。

首先,服务定位器隐藏了依赖关系。在您的第二个示例中,仅查看公共接口,无法知道ProductControllers需要存储库。

更重要的是,我必须回应OdeToCode。我认为

IProductRepository repository = Mockery.NewMock<IProductRepository>();
IProductController controller = new ProductController(repository);

ObjectFactory.SetFactory(IProductRepository, new MockRepositoryFactory())
IProductController controller = new ProductController();

特别是如果在测试夹具的SetUp方法中配置了 ObjectFactory。

最后,服务定位器模式在至少一种特殊情况下显然是次优的:当您编写的代码将被编写您无法控制的应用程序的人使用时。我打赌人们通常更喜欢构造函数注入(或其他 DI 方法之一),因为它适用于所有场景。为什么不使用涵盖所有情况的方法呢?

(Martin Fowler 在“Inversion of Control Containers and the Dependency Injection Pattern”中提供了更彻底的分析,特别是“Service Locator vs Dependency Injection”一节)。

于 2009-06-25T15:33:36.790 回答
4

当您使用第二种方法时,缺点是:

  • 需要大量不可读的测试设置/上下文方法
  • 容器与控制器耦合
  • 您将需要编写更多代码

当您不想要依赖注入时,为什么还要使用 ioc 容器?

于 2009-06-25T15:14:00.217 回答