自从我阅读了关于另一个 stackoverflow 问题的答案(现在我不知道确切的问题)的答案以来,一直困扰着我的事情是,用户说“如果您正在调用服务定位器,那么您做错了。 ”
这是一个声望很高的人(我想有几十万)所以我倾向于认为这个人可能知道他们在说什么。自从我第一次开始了解 DI 以及它与单元测试的关系以及不相关的情况以来,我一直在我的项目中使用 DI。这是我现在相当舒服的事情,我想我知道我在做什么。
但是,有很多地方我一直在使用服务定位器来解决项目中的依赖关系。一旦主要示例来自我的 ModelBinder 实现。
典型模型粘合剂的示例。
public class FileModelBinder : IModelBinder {
public object BindModel(ControllerContext controllerContext,
ModelBindingContext bindingContext) {
ValueProviderResult value = bindingContext.ValueProvider.GetValue("id");
IDataContext db = Services.Current.GetService<IDataContext>();
return db.Files.SingleOrDefault(i => i.Id == id.AttemptedValue);
}
}
不是真正的实现——只是一个简单的例子
由于第一次请求Binder 时 ModelBinder 实现需要一个新实例,因此不可能在此特定实现的构造函数上使用依赖注入。
我的很多课都是这样。另一个例子是缓存过期进程,只要缓存对象在我的网站中过期,它就会运行一个方法。我运行了一堆数据库调用,什么都没有。我也在使用服务定位器来获取所需的依赖项。
我最近遇到的另一个问题(我在这里发布了一个问题)是我所有的控制器都需要一个 IDataContext 的实例,我使用 DI 来处理它——但是一个操作方法需要一个不同的 IDataContext 实例。幸运的是,Ninject 带来了一个命名依赖项。然而,这感觉像是一个杂牌,而不是一个真正的解决方案。
我认为我至少对关注点分离的概念理解得相当好,但我对依赖注入和服务定位器模式的理解似乎存在根本性的错误——我不知道那是什么。
我目前理解它的方式 - 这也可能是错误的 - 是,至少在 MVC 中,ControllerFactory 为 Controller 查找构造函数并调用 Service Locator 本身以获取所需的依赖项,然后将它们传递进去。但是,我可以理解,不是所有的类和什么都没有工厂来创建它们。所以在我看来,一些服务定位器模式是可以接受的......但是......
- 什么时候不能接受?
- 当我应该重新考虑如何使用服务定位器模式时,我应该注意哪种模式?
- 我的 ModelBinder 实现错了吗?如果是这样,我需要学习什么来解决它?
- 在另一个与该用户类似的问题中,Mark Seemann推荐了一个抽象工厂——这有什么关系?
我想就是这样 - 我真的想不出任何其他问题来帮助我理解,但非常感谢任何额外的信息。
我知道 DI 可能不是所有问题的答案,而且我在实现它的方式上可能有些过火,但是,它似乎以我期望的方式工作,与单元测试一起工作,而不是什么。
我不是在寻找代码来修复我的示例实现——我在寻找学习,寻找解释来修复我有缺陷的理解。
我希望 stackoverflow.com 能够保存草稿问题。我也希望回答这个问题的人在回答这个问题时获得适当的声誉,因为我认为我要求很多。提前致谢。