One of the things that was in AutoGen from version 0.001 was the ability to intercept Dispose. This might seem like a relatively minor concern, but it was actually central to the design. First the bad news: after a lot of work, the Dispose functionality still had edge-case failures. The truth is, the lifestyle aspects of Windsor are quite complex, and any Dispose interception implementation needs to understand it completely. So why did I bother? And why is Krzysztof bothering now?
We need to return to one of the basic principles of IoC containers: the code being hosted shouldn’t need to know it’s being hosted. It’s this design philosophy that sets it apart from EJB, ASP.NET and any number of other hosting technologies. The release method violates this badly. Even if you hide the container behind an abstract factory it’s not good enough: you’ll need to add lifecycle concerns directly to the factory interface. Windsor provides an API for releasing resources that goes against the grain of .NET development. If you create an object in a using statement and it goes out of scope, you’ve got a reasonable expectation that you’re done with that object.
Container independence may not be a concern to many, but it breaks that too. Every abstraction that sits on top of Castle has to know about this detail or it will end up leaking instances. It pretty much breaks the Common Service Locator: there’s just no sensible implementation of it that doesn’t involve providing a footnte saying “I hope you remember to call IWindsorContainer.Release at the appropriate times.”*
Does it matter? Well, like all resource leaks, it depends. But in certain circumstances, it will.
What can we do?
Intercepting IDisposable isn’t ideal either; for a start, you’d need to proxy absolutely everything that implements IDisposable to get it to work. There’s a couple of other alternatives I can think of here:
- Leave it the way that it is and pretend it’s a user problem. (You may suspect I don’t favour this option.)
- Remove the functionality that requires Windsor hold the reference. (This might be easier said than done.)
- Start holding onto transients using WeakReferences. (Ditto)
UPDATE: Krzysztof has pointed out that the WeakReference proposal may be a cure worse than the disease, since it relies on Finalizers to work.
*Some readers may object that, even if releasing individual instances is relatively hard, you can always get rid of the lot by disposing of the container. This would, of course, assume that your factory implemented IDisposable, which sadly the Common Service Locator doesn’t. Siege, thankfully, does, so it’s at least possible to do that if you’re using Marcus’ code.