воскресенье, 12 сентября 2010 г.

Windsor Castle BuildUp

Good news, everyone! I've discovered a way to enhance a brilliant DI-container Castle Windsor with not so brilliant feature as BuildUp.

Saying that it is not that brilliant I mean that this feature is a beast, actually. It is an open door to violate DI principles, and there are more elegant ways to overcome a problem of having to resolve an external object through DI-container. After all, if Castle team considered this feature useful, they would roll it out long time ago, have no doubt!
However, in my case it is a matter of time, to have an opportunity of resolving existing object's dependencies through DI-container, built as fast as possible. That is why I turned to BuildUp feature that some other DI-frameworks have.

I was really amused with Windsor's degree of extendability and how trivial my solution appeared.

BuildUp functionality is closed up under ComponentActivator. Activators are called when LifetimeManager considers that a new object has to be created. And that logically brings us to restriction of this solution - it won't work with Singleton lifestyle. But it shouldn't actually! When you mark an object as a singleton - you effectively state that a container is going to be an owner of that object, thus it won't ever be built externally.



BuildUpComponentActivator extends DefaultComponentActivator and overrides a single method - Instantiate. This guy is a cheater, as you might guess, it never creates an object, but simply read it from context. All the dirty job of deriving dependencies is done by a parent class. Should BuildUpComponentActivator fail to find an object in context, it will simply delegate all work to parent, and a new object will be created. This is done to support resolving objects of the same type managed by container.

Context is a dictionary, created with BuildUp extension method:



In order to be able to build up an object, one have to modify it's registration and override ComponentActivator setting. CanBeBuiltUp is a neat extension method wrapping this call for Windsor fluent registration API.

There is only one shortcoming with this solution I came with - it doesn't provide you with any facilities to release this external object's dependencies. It has to be done manually somewhere.

Please note, that there are other solutions to this problem.

Good luck!

Комментариев нет: