Can Castle Windsor be used to implement IDependencyResolver in ASP.NET MVC 4?
Asked Answered
C

3

6

I read this article and saw many people commented that do not use Castle Windsor to implement IDependencyResolver in ASP.NET MVC3 and stick with a custom IControllerFactory. Basically my questions now are:

  1. Do not use Castle Windsor to implement IDependencyResolver. Is this still true in ASP.NET MVC 4 ?

  2. If 1 is the case. Can any other DI container (Unity, StructureMap) has the same problem as Castle Windsor? Can I use any alternative?

Thanks a lot

EDIT

Sounds to me that Castle Windsor should NOT be used to implement IDependencyResolver. I have decided to use some other DI container, such as StructureMap

Caliche answered 17/8, 2013 at 22:23 Comment(1)
@ sean717,Did you read comments in your link inside question?Indiscernible
R
4

There is no difference between MVC3 and MVC4 in regards to IDependencyResolver, other than the fact there is a separate resolver for WebAPI.

In my opinion, Mike Hadlow is a bit too caustic on this subject, and many other people have jumped on the bandwagon without truly considering why.

Yes, it's true that Castle Windsor has a specific object lifestyle (ie lifetime management object) called Pooled that often requires you to call Release on it. And when using this lifestyle, you should probably not use IDependencyResolver because it does not provide access to this Release method (although there are ways around that too).

However, I feel it's generally bad to use this lifestyle in a web application, and you should instead use the PerWebRequest lifestyle, which will automatically release objects at the end of the web request. If this is what you are using, then there is no problem with using IDependencyResolver with Castle Windsor.

Why do I think Hadlow is too caustic? Well, because he bases his entire argument on this:

"That’s right, no ‘Release’ method. You can provide a service from your IoC container, but there’s no way to clean it up. If I was going to use this in Suteki Shop, I would have a memory leak of epic proportions."

He then goes on to reference Krzysztof Koźmic's article regarding lifestyle management, but neglects to reference his followup article which I will do here:

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

Note what he says here:

"Since as I men­tioned in my pre­vi­ous post, Wind­sor will track your com­po­nent, it’s a com­mon mis­con­cep­tion held by users that in order to prop­erly release all com­po­nents they must call Release method on the container."

He goes on to talk about various other aspects as well, but in general, I don't think most people will be using Pooled or Transient objects that required disposal in a web application. And if you do, then you should know not to use IDependencyResolver then. Otherwise, you should have no problems.

I know I will probably get a lot of grief from people arguing otherwise, but I simply do not see this as the end of the world issue that people like Hadlow seem to think it is, since there are so many alternatives, and workarounds even when you do need to call Release.

Besides all this, using a lifestyle that requires calling Release means extra work for you, the developer. You now have to manage the object lifetimes and remember to dispose of objects, and failing to do so creates memory leaks. This is, essentially, nullifying the benefits of garbage collection in my opinion. I only ever use transient objects with things that do not need disposal, and I never use pooled objects.

By the way, I may be wrong, but I don't think any other container has this problem. This leads me to the conclusion that it's Windsor that is broken, rather than MVC, when every other container out there seems to not have an issue with this. Windsor likes to stubbornly hang on to its version of reality though, so YMMV.

Rhetic answered 18/8, 2013 at 5:52 Comment(2)
"I don't think most people will be using Pooled or Transient objects that required disposal in a web application" – well, i used transient object and i had to learn this lesson in a very hard way. So i still stick with IControllerFactorySuspicious
@Meixger - Can you explain why you need an object who's lifetime needs to be disposed faster than the span of a web request?Rhetic
O
3

The advice not to use IDependencyResolver is silly, because it can be used with Castle Windsor, even though the interface lacks a release method. The solution is simply to let the IDependencyResolver implementation cache each requested instance (in a cache bounded to the web request, using HttpContext.Items for instance). At the end of the web request all cached instances (usually just a few) can be released.

To be able to release all instances at the end of the web request, you should either register an Request_Ends event in the global.asax or register a HttpModule that does this.

You can call this a workaround, but not using the IDependencyResolver is not really an option, since it is too deeply integrated with MVC. Besides, other containers (such as Ninject and Simple Injector) use this same approach (using an HttpModule) to 'release' instances.

It's unfortunate though, that there isn't an official NuGet packages for omtegrating Windsor with MVC, since now you'll have to implement this yourself. All other frameworks do have such package btw. But again, it isn't that hard to implement this yourself.

Other IoC containers already show that it is possible to implement release as an implementation detail and you don't need Release as part of the IDependencyResolver contract. The MVC designers actually did the right thing by removing such method from the API.

Ovoviviparous answered 18/8, 2013 at 18:6 Comment(0)
T
2

While I agree implementing IDependencyResolver is possible and not terribly difficult.. and yes, depending on the lifestyles at play, explicitly Release()'ing may not matter... and yes, there are ways to force a Release() by caching the instance somewhere as well as other subtle tricks - I think this is alot to leave to interpretation and can be problematic and hard to track down. Understanding when Windsor is going to track an instance isn't always immediately obvious (i.e. if the component has decommission concerns vs. not, lifestyle, etc.). One of the core value-add's of IoC is to centralize the responsibility of object creation and instance management. To properly do that and have separation of concerns - you need to have an architecture that you can trust will serve you well in call scenarios and that IMO means having a iron clad answer for Release()'ing instance of all flavors. My advice is to always implement a design that will allow Release to be called - especially on roots (i.e. a Controller).

The final argument against IDependencyResolver is you have to register a number of MVC system components if you integrate at this level. That's too intimate of a dance between my app and the framework beneath it for my taste. IControllerFactory gives a much more targeted integration point, you don't have to register MVC system components and you get a Release() hook. So, unless you want to override MVC System components, I see very little reason to implement IDepedencyResolver over IControllerFactory. I see the opposite argument in fact. I personally wised up to this on this thread over here which shows both approaches.

Hope this helps

Touching answered 18/8, 2013 at 22:33 Comment(6)
This argument contradicts itself. If it's so important for the container to be responsible for releasing, why does it require you to tell it when to release? Obviously that argument is flawed, because you still depend on the app to control when it happens and not the container. This argument also ignores the fact that IDependencyResolver is used for a lot more than just instancing controllers, and using a custom IControllerFactory doesn't solve those issues, so now you have to implement other extension points as well.Rhetic
Easy tiger... I didn't write Windsor. I'm just telling you how to best work with it based on my experiences and a great deal of reading. Its tracking feature is controversial, but I've come to like it after I took the time to understand it. If you dint like Windsor there are plenty of other containers out there. Oh, and I made it clear that IDependencyResolver is only needed iiiiiiiiif you don't want to override MVC System components.Touching
No, I believe you are mindlessly propagating the myth that IDependencyResolver is broken, despite there being lots of evidence to the contrary. Even Krzysztof says that idea of calling Release on everything is a misconception. He says point blank "You never have to call Release" if your app is well designed. My point is that the argument those in favor of ignoring IDependencyResolver use is self-defeating, and illogical. It says that the container must be responsible for the lifetime of the object, but then also says that the lifetime is to be controlled externally by calling release.Rhetic
I was also arguing against your comment that using IDependencyResolver requires registering "too many" things.. which doesn't make sense, since if you don't use IDependencyResolver you have to register multiple things as well in order to get the full benefits, such as a FilterProvider that uses the container (MVC uses IDependencyResolver for this, so you have to do it manually), And Default model binder (again, MVC will use the IDR to resolve models, if you don't register it you have to provide your own to get the same functionality), and a number of other extension points.Rhetic
I assume you're talking about this: devlicio.us/blogs/krzysztof_kozmic/archive/2010/08/27/… Yes, if you're pulling from the container, you've got a design problem. But if you're using a lifestyle that doesn't have a end event that the container is aware... you absolutely have to release it. It's very easy to create leaks in my experience and the experience of the ~70 developers I work w/. I see it on a daily basis in cases that aren't container abuse. It's a lot easier to call Release in my experience, but do whatever you want to do.Touching
And I don't know what you're talking about regarding "since if you don't use IDependencyResolver you have to register multiple things as well in order to get the full benefits". 99% of the time, people are doing this to have Windsor create the Controller - they don't care about all that other stuff. If you implement IDependencyResolver to have Windsor create controllers then you have to register all that other stuff or you will get an exception. If you want to override that stuff then yes... IDependencyResolver is what you want, but not if all you care about is controllers.Touching

© 2022 - 2024 — McMap. All rights reserved.