This post is a playground for me, to try out some ideas I want to include in my talk about Windsor at KGD.NET meeting later this month.
We have a messaging application built around two interfaces:
Hopefully I don’t have to explain how they work. The idea is, application receives commands from somewhere, then it pulls all handlers registered for this command and let them handle the command. Split of Handler interface into generic and non-generic part is there to make up for lack of co/contra-variance in .NET 3.5.
Commands and Handlers
Handlers are quite simple classes implementing closed version of Handler<> interface. For example to change client’s address we’d have the following command
and its handler:
Nothing earth shattering here. We would have similar set up for other business events in the application. We assume we can have more than one handler for single command (for example another handler would update shipping costs and promotions available for the new address of the client).
The ability to pull multiple services from the container via typed factory is not available in Windsor 2.1.1 – you need the trunk version to take advantage of it.
To register the code we create an installer:
There are a couple interesting things here. First we register typed factory facility, which we’ll use later on to pull handlers for commands we receive. Then we register custom selector for typed factory (discussed below), and an interceptor (discussed below). Then we register all repositories and all handlers from given assembly, configuring handlers with transient lifestyle and with the interceptor we registered above. Lastly we also register typed factory for handlers:
Typed factory selector
The handler factory has to do quite a lot of work for us. Given an instance of a command, it has to pull from the container all the handlers for the command’s type. To do this we need to use a custom selector (and trunk version of Windsor).
Based on the command’s type we create closed Handler<> type and return TypedFactoryComponentCollection (new type that pulls all components for given service) passing down the command as typed argument to the resolution.
Putting it all together
We can now use the code like this:
Notice how simple the calling code is. It has no knowledge of the (quite complex) process that takes place behind the scenes to create strongly typed instances of appropriate classes. It does not even know what actual type of command it got.
What about releasing transient handlers?
Isn’t this code too simple though? It resolves handlers, which are transient components and it does not release them. And we all know transient components need to be released in Windsor, right?
Well – it does release them actually, it just doesn’t do it explicitly. Remember we registered an interceptor with all handlers. Here’s how that interceptor looks like:
The interceptor releases the component after the call to Execute for us. Thanks to this we take the burden (no pun intended) of releasing the components from the callers, and we make sure our handlers won’t leak memory. This is quite a useful trick actually, and while I have precisely zero knowledge of NServiceBus, I think it could be used to fix the issue Davy discussed, without having to mess with release policy.