我阅读this article并看到很多人评论说不要使用Castle Windsor在ASP.NET MVC3中实现IDependencyResolver并坚持使用自定义IControllerFactory。基本上我现在的问题是:
请勿使用Castle Windsor实施IDependencyResolver。在ASP.NET MVC 4 中仍然如此吗?
如果是1的话。任何其他DI容器(Unity,StructureMap)都有与Castle Windsor相同的问题吗?我可以使用任何替代方案吗?
非常感谢
修改
听起来我不应该使用Castle Windsor来实现IDependencyResolver
。我决定使用其他一些DI容器,例如StructureMap
答案 0 :(得分:4)
MVC3和MVC4在IDependencyResolver方面没有区别,除了WebAPI有一个单独的解析器。
在我看来,Mike Hadlow在这个问题上有点过于苛刻,而且很多其他人在没有真正考虑原因的情况下加入了这个行列。
是的,Castle Windsor确实有一个特定的对象生活方式(即终身管理对象),称为Pooled,通常需要您在其上调用Release。在使用这种生活方式时,您可能不应该使用IDependencyResolver,因为它不提供对此Release方法的访问(尽管也有方法)。
但是,我觉得在Web应用程序中使用这种生活方式通常很糟糕,您应该使用PerWebRequest生活方式,它会在Web请求结束时自动释放对象。如果这是您正在使用的,那么使用IDependencyResolver与Castle Windsor没有任何问题。
为什么我认为哈德洛太腐蚀?好吧,因为他的全部论点都基于此:
“没错,没有'释放'方法。你可以从你的IoC容器中提供服务,但没有办法清理它。如果我打算在Suteki商店使用它,我会有内存泄漏史诗般的比例。“
然后他继续参考KrzysztofKoźmic关于生活方式管理的文章,但忽略了参考他将在这里做的后续文章:
http://kozmic.net/2010/08/27/must-i-release-everything-when-using-windsor/
请注意他在这里说的话:
“正如我在上一篇文章中所提到的,Windsor将跟踪您的组件 这是用户常见的误解 ,为了正确释放所有组件,他们必须在容器上调用Release方法。“
他继续谈论其他各个方面,但总的来说,我认为大多数人都不会使用需要在Web应用程序中处理的Pooled或Transient对象。如果你这样做,那么你应该知道不要使用IDependencyResolver。否则,你应该没有问题。
我知道我可能会从别人的争论中得到很多的悲痛,但我根本不认为这是世界问题的终结,像Hadlow这样的人似乎认为它是,因为有很多选择,并且即使您确实需要调用Release,也可以解决此问题。
除此之外,使用需要调用Release的生活方式意味着为开发人员提供额外的工作。您现在必须管理对象生存期并记住处置对象,否则会导致内存泄漏。在我看来,这基本上使垃圾收集的好处无效。我只使用不需要处理的东西的瞬态对象,我从不使用合并的对象。
顺便说一下,我可能错了,但我不认为任何其他容器有这个问题。这让我得出的结论是,当其他每个容器似乎都没有问题时,Windsor就会被打破,而不是MVC。温莎喜欢顽固地坚持其现实版本,所以YMMV。
答案 1 :(得分:3)
不使用IDependencyResolver
的建议很愚蠢,因为它可以与Castle Windsor一起使用,即使界面缺少释放方法。解决方案就是让IDependencyResolver
实现缓存每个请求的实例(例如,使用HttpContext.Items
在与Web请求相关的缓存中)。在Web请求结束时,可以释放所有缓存的实例(通常只有几个)。
为了能够在Web请求结束时释放所有实例,您应该在global.asax中注册Request_Ends
事件或注册执行此操作的HttpModule
。
您可以将此称为解决方法,但不使用IDependencyResolver
实际上不是一种选择,因为它与MVC的集成太深。此外,其他容器(如Ninject和Simple Injector)使用相同的方法(使用HttpModule)来“释放”实例。
不幸的是,没有一个官方的NuGet软件包可以将Windsor与MVC一起使用,因为现在你必须自己实现它。所有其他框架都有这样的包btw。但同样,自己实现这一点并不难。
其他IoC容器已经表明可以将发布实现为实现细节,并且Release
合同中不需要IDependencyResolver
。 MVC设计者实际上通过从API中删除这样的方法做了正确的事情。
答案 2 :(得分:2)
虽然我同意实现IDependencyResolver是可能的并且不是非常困难..是的,根据游戏中的生活方式,明确释放()可能并不重要......是的,有办法强制释放()通过在某个地方缓存实例以及其他微妙的技巧 - 我认为这很多都会留给解释,可能会有问题,很难追查。了解温莎什么时候跟踪一个实例并不总是很明显(即如果该组件有退役问题与否,生活方式等)。 IoC的核心增值之一是集中对象创建和实例管理的责任。要正确地做到这一点并分离关注点 - 你需要有一个你可以信任的架构能在呼叫场景中为你提供良好的服务,并且IMO意味着对于Release()所有类型的实例都有一个铁板的答案。我的建议是始终实现一个允许调用Release的设计 - 特别是在根(即控制器)上。
针对IDependencyResolver的最后一个参数是,如果在此级别进行集成,则必须注册许多MVC系统组件。根据我的口味,我的应用程序和它下面的框架之间的舞蹈太亲密了。 IControllerFactory提供了一个更有针对性的集成点,您不必注册MVC系统组件,而是获得Release()钩子。因此,除非你想覆盖MVC系统组件,否则我认为很少有理由在IControllerFactory上实现IDepedencyResolver。事实上,我看到了相反的论点。我亲自在thread over here上看到了这一点,这显示了两种方法。
希望这有帮助