【发布时间】:2011-06-04 04:37:55
【问题描述】:
自从我阅读了关于另一个 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 来实现 - 但是 one 操作方法需要一个不同的实例数据上下文。幸运的是,Ninject 带来了一个命名依赖项。然而,这感觉像是一个杂物,而不是真正的解决方案。
我认为我至少对关注点分离的概念有相当好的理解,但我对依赖注入和服务定位器模式的理解似乎存在根本性的错误——我不知道那是什么。
我目前理解它的方式 - 这也可能是错误的 - 是,至少在 MVC 中,ControllerFactory 为 Controller 查找构造函数并调用服务定位器本身以获取所需的依赖项,然后传递它们但是,我可以理解,不是所有的类和什么都没有工厂来创建它们。所以在我看来,一些服务定位器模式是可以接受的......但是......
- 什么时候不能接受?
- 当我应该重新考虑如何使用服务定位器模式时,我应该注意哪种模式?
- 我的 ModelBinder 实现有错吗?如果是这样,我需要学习什么来解决它?
- 在另一个问题中,一位用户 Mark Seemann 推荐了一个抽象工厂 - 这有什么关系?
我想就是这样 - 我真的想不出任何其他问题来帮助我理解,但非常感谢任何额外的信息。
我知道 DI 可能无法解决所有问题,而且我在实现它的方式上可能有些过火,但是,它似乎以我期望的方式与单元测试一起工作,而并非如此。
我不是在寻找代码来修复我的示例实现 - 我在寻找学习,寻找解释来修复我有缺陷的理解。
我希望 stackoverflow.com 能够保存草稿问题。我也希望回答这个问题的人在回答这个问题时获得适当的声誉,因为我认为我要求很多。提前谢谢。
【问题讨论】:
-
我认为您指的是 Mark Seeman 和这篇博文:blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx
标签: dependency-injection asp.net-mvc-3 ninject service-locator abstract-factory