Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Castle Windsor - Do I have to release singleton or non-disposable transient objects?

The Castle wiki says at several places I should ALWAYS call container.Release() for components resolved through the container. This obviously makes sense for sophisticated life-style management techniques (e.g. LifeStyle.Pooled) or when using specialized facilities...

But do I really have to release singleton (which live until the container is disposed) and non-disposable transient objects? If I step through Release() calls for transient objects or singletons these calls seem to be superfluous - .e.g. in the case of transient objects not implementing IDisposable the kernel simply notices that it has no track of the object and returns...

There seems to be the concept of a "component burden" to track "indirect" references to other disposable components that might be constructed while resolving a transient object. I understand that it is necessary to release transient objects if you do not know 100% whether they have such indirect dependencies or not. Is this the main reason to "urge" all Castle users to ALWAYS release components?

like image 636
blueling Avatar asked Jul 26 '10 11:07

blueling


1 Answers

Castle Wiki is a bit strict here - trying to be safe rather than sorry. It could use some rewording there probably.

Anyway - here's how it works.

Windsor (by default) tracks most components and it holds reference to them which stops Garbage Collector from collecting them. This is not a bug - it's a feature, and a extremely useful and powerful one. In most cases you should not assume if a component will be tracked or not. A non-disposable component that has disposable dependencies will also be tracked. This is in general rule: "components that either themselves of some of their dependencies have any decommission steps are tracked by default release policy in Windsor".

Now, here's the part where lifetimes come into play.

  • Singleton - by definition singleton are "global" in the context of the container - they get created when you first request them and live for the rest of the lifetime of the container (which means until the container gets disposed). If you see documentation, it actually says that releasing singletons actually doesn't do anything. It's only when the container gets disposed that decommission concerns of your lifetime components will get called.

  • Per (context: web request/WCF Session/) - since the object is shared in a well defined context with a well define end, end of the context will take care of releasing your components.

  • Transient - That's where the real issues can creep in. Since transient components don't have any end arbitrary end of lifetime and you can produce heaps of their instances during the lifespan of the app, there's no other way than being explicit and saying to the container "hey, I'm not gonna use this object anymore, feel free to get rid of it, thanks for all the fish."

Now the reason why the documentation suggest always releasing the components is that the code that uses components should not really know what the lifetime of a component is. It is not always the case, and often in applications there are components that "naturally" fit a lifestyle. In general however, like I said it's about being safe rather than sorry.

Another thing is where you call the Resolve and Release. You should only ever Release what you Resolve.

When you use the container in similar manner to how I do it, you may not have to call Release anywhere in your code. You will Resolve your root, but Dispose of the container itself will take care of releasing it. You will likely also resolve other components implicitly via typed factories, and in this case you should also release them (via the factory), but that's usually it.

So the end result is, it's not as scary as it sounds at first.

like image 158
Krzysztof Kozmic Avatar answered Oct 26 '22 06:10

Krzysztof Kozmic