在我在网上看到的大多数样本中,MVC控制器中的DI都是这样完成的
public ProductController(IProductRepository Rep) { this._rep = Rep; }
使用自定义ControllerFactory,它使用选择的DI框架并注入存储库.
为什么以上认为比上述更好
public ProuctController() { this._rep = ObjectFactory.GetInstance(); }
这将得到相同的结果,但不需要自定义控制器工厂.
就测试而言,测试应用程序可以有一个单独的BootStrapper.这样,当控制器被测试时,他们可以获得假的存储库,当它们被用于实际时,它们将获得真实存储库.
第二个构造函数的主要缺点是现在必须为每个测试正确配置IoC容器.随着代码库的增长和测试场景的变化,这种设置可能成为真正的负担.当您明确传入测试双精度时,测试通常更容易阅读和维护.
另一个问题是将大量类与特定的DI/IoC框架耦合.当然,有很多方法可以将它抽象出去,但是在整个类中仍然存在代码,以检索依赖项.由于所有优秀的框架都可以通过查看构造函数来确定您需要哪些依赖项,因此需要大量浪费精力和重复代码.
由于多种原因,构造函数注入(第一种方法)优于服务定位器模式(第二种方法).
首先,服务定位器隐藏了依赖关系.在您的第二个示例中,仅查看公共接口,无法知道ProductControllers
需要存储库.
更重要的是,我必须回应OdeToCode.我认为
IProductRepository repository = Mockery.NewMock(); IProductController controller = new ProductController(repository);
比...更清楚
ObjectFactory.SetFactory(IProductRepository, new MockRepositoryFactory()) IProductController controller = new ProductController();
特别是如果在测试夹具的SetUp
方法中配置了ObjectFactory .
最后,服务定位器模式在至少一个特定情况下显然是次优的:当您编写的代码将由人们在您的控件之外编写应用程序时使用.我打赌人们通常更喜欢构造函数注入(或其他DI方法之一)因为它适用于每个场景.为什么不使用涵盖所有情况的方法?
(Martin Fowler在"控制容器的反转和依赖注入模式"中提供了更全面的分析,特别是"服务定位器与依赖注入"部分).