在ASP.NET MVC控制器中注入依赖项的不同方法?

时间:2009-06-25 14:54:51

标签: asp.net-mvc dependency-injection structuremap

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

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

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

为什么以上认为优于

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

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

就测试而言,测试应用程序可以有一个单独的BootStrapper。这样,当控制器被测试时,他们可以获得假的存储库,当它们被用于实际时,它们将获得真实存储库。

3 个答案:

答案 0 :(得分:5)

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

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

答案 1 :(得分: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"中提供了更全面的分析,特别是“服务定位器与依赖注入”部分。)

答案 2 :(得分:4)

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

  • 需要庞大且难以理解的测试设置/上下文方法
  • 容器耦合到控制器
  • 您需要编写更多代码

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