6

我读了这篇文章,看到很多人评论说不要使用 Castle Windsor 在 ASP.NET MVC3 中实现 IDependencyResolver 并坚持使用自定义 IControllerFactory。基本上我现在的问题是:

  1. 不要使用 Castle Windsor 来实现 IDependencyResolver。这在 ASP.NET MVC 4中仍然成立吗?

  2. 如果是 1 的话。任何其他 DI 容器(Unity、StructureMap)都可以有与 Castle Windsor 相同的问题吗?我可以使用任何替代方案吗?

非常感谢

编辑

在我看来,Castle Windsor 不应该用于实施IDependencyResolver。我决定使用其他一些 DI 容器,例如 StructureMap

4

3 回答 3

4

在 IDependencyResolver 方面,MVC3 和 MVC4 之间没有区别,除了 WebAPI 有一个单独的解析器。

在我看来,迈克哈德洛在这个问题上有点过于刻薄了,许多其他人在没有真正考虑原因的情况下就加入了这个潮流。

是的,Castle Windsor 确实有一个特定的对象生活方式(即生命周期管理对象),称为 Pooled,通常需要您对其调用 Release。在使用这种生活方式时,您可能不应该使用 IDependencyResolver,因为它不提供对此 Release 方法的访问(尽管也有解决方法)。

但是,我觉得在 Web 应用程序中使用这种生活方式通常很糟糕,您应该改用 PerWebRequest 生活方式,它会在 Web 请求结束时自动释放对象。如果这是您正在使用的,那么将 IDependencyResolver 与 Castle Windsor 一起使用是没有问题的。

为什么我认为哈德洛太刻薄了?好吧,因为他的整个论点都基于此:

“没错,没有‘Release’方法。你可以从你的 IoC 容器中提供服务,但没有办法清理它。如果我要在 Suteki Shop 中使用它,我会遇到史诗般的内存泄漏。 "

然后,他继续引用 Krzysztof Koźmic 关于生活方式管理的文章,但忽略了引用他的后续文章,我将在此处介绍:

http://kozmic.net/2010/08/27/must-i-release-everything-when-using-windsor/

注意他在这里说的话:

“正如我在上一篇文章中提到的,Windsor 会跟踪你的组件,这是用户普遍持有的一个误解,即为了正确释放所有组件,他们必须在容器上调用 Release 方法。”

他还谈到了其他各个方面,但总的来说,我认为大多数人不会使用需要在 Web 应用程序中处理的池化或瞬态对象。如果你这样做了,那么你应该知道不要使用 IDependencyResolver。否则,您应该没有问题。

我知道我可能会从争论不休的人那里得到很多悲伤,但我根本不认为这是像哈德洛这样的人认为的世界末日问题,因为有很多选择和解决方法,即使当您确实需要致电 Release。

除此之外,使用需要调用 Release 的生活方式对开发人员来说意味着额外的工作。您现在必须管理对象的生命周期并记住处置对象,否则会导致内存泄漏。在我看来,这基本上抵消了垃圾收集的好处。我只对不需要处理的东西使用瞬态对象,而且我从不使用池对象。

顺便说一句,我可能错了,但我认为其他任何容器都没有这个问题。这使我得出的结论是,当所有其他容器似乎都没有问题时,是 Windsor 坏了,而不是 MVC。温莎喜欢固执地坚持它的现实版本,所以 YMMV。

于 2013-08-18T05:52:18.543 回答
3

不使用的建议IDependencyResolver是愚蠢的,因为它可以与 Castle Windsor 一起使用,即使界面缺少发布方法。解决方案只是让IDependencyResolver实现缓存每个请求的实例(在与 Web 请求绑定的缓存中HttpContext.Items,例如使用)。在 Web 请求结束时,可以释放所有缓存的实例(通常只有几个)。

为了能够在 Web 请求结束时释放所有实例,您应该Request_Ends在 global.asax 中注册一个事件或注册一个HttpModule执行此操作的事件。

您可以将此称为一种解决方法,但不使用IDependencyResolver它并不是一个真正的选择,因为它与 MVC 集成得太深。此外,其他容器(例如 Ninject 和 Simple Injector)使用相同的方法(使用 HttpModule)来“释放”实例。

不幸的是,没有官方的 NuGet 包用于将 Windsor 与 MVC 集成,因为现在您必须自己实现它。顺便说一句,所有其他框架都有这样的包。但同样,自己实现这一点并不难。

其他 IoC 容器已经表明可以将发布作为实现细节来实现,而您不需要将Release其作为IDependencyResolver合同的一部分。MVC 设计者实际上做了正确的事情,从 API 中删除了这种方法。

于 2013-08-18T18:06:17.987 回答
2

虽然我同意实现 IDependencyResolver 是可能的并且不是非常困难.. 是的,根据生活方式,明确的 Release()'ing 可能无关紧要......是的,有一些方法可以通过缓存来强制 Release()例如某处以及其他微妙的技巧 - 我认为这有很多需要解释,并且可能有问题且难以追踪。了解 Windsor 何时将跟踪实例并不总是显而易见的(即,组件是否存在退役问题与否、生活方式等)。IoC 的核心增值之一是集中了对象创建和实例管理的责任。要正确地做到这一点并分离关注点 - 您需要有一个您可以信任的架构,它将在呼叫场景中为您提供良好的服务,并且 IMO 意味着对所有风格的 Release() 实例都有一个铁定的答案。我的建议是始终实现允许调用 Release 的设计 - 特别是在根(即控制器)上。

反对 IDependencyResolver 的最后一个论点是,如果您在此级别集成,则必须注册许多 MVC 系统组件。我的应用程序和它下面的框架之间的舞蹈太亲密了,不适合我的口味。IControllerFactory 提供了一个更有针对性的集成点,您不必注册 MVC 系统组件并且您会获得一个 Release() 挂钩。因此,除非您想覆盖 MVC 系统组件,否则我认为几乎没有理由在 IControllerFactory 上实现 IDepedencyResolver。事实上,我看到了相反的论点。我个人在这个线程上对此很明智,它显示了这两种方法。

希望这可以帮助

于 2013-08-18T22:33:24.720 回答