Castle Windsor resolution logic: Cool handler filter that orders components

As you can see from my previous post on handler filters, an IHandlersFilter will have a chance to do stuff to the array of handlers that would otherwise be used untouched during a call to ResolveAll ( ResolveAll is also what happens behind the scenes when a component relies on CollectionResolver to supply a collection of components for it to use).

Now, what is left is to implement some kind of logic that does something to the handlers array. First thing that comes to my mind is ordering the handlers!

Ordering the handlers is very relevant e.g. in scenarios where tasks are modeled as a series of steps that should be executed in a consistent fashion. An example could be a component ( TaskProcessor) that gets a collection of implementations of some task-like interface injected ( IEnumerable<ITask>).

Now, to ensure that this list of tasks is properly ordered, I’d like to specify a few hints on how they should be ordered. Not too little, because otherwise stuff would not work, but I also don’t want to be overly explicit on how the tasks should be ordered.

So I came up with a solution based on two attributes: ExecutesBeforeAttribute and ExecutesAfterAttribute, allowing types to position themselves in relation to other types they know about, and all other types to stay oblivious of what is going on.

One possible usage scenario could look like this, assuming we have modeled some kind of money transfer as a series of steps, each implementing ITask:

and then a simplistic executor:

Now, carrying out a money transfer would consist of having the executor run through this list of discrete tasks, but it’s probably important that the validation occurs before the actual payment, and it probably doesn’t make sense to generate reports before the payment. Therefore, let’s decorate some of the steps:

and then make sure we respect them:

Now, when the container builds a TaskExecutor, it will inject the ITask implementations in the order specified by the attributes. Inside RespectOrderDirectivesHandlersFilter, there’s a HandlerSorter, which is the implementation of the actual sorting algorithm. It builds a directed graph out of components and their dependents, and then it orders the components so that they will be traversed in a way that respects the order specified by the attributes. I’m not an expert on graph algorithms, so I don’t know if my implementation is really really stupid and slow – but I know that a) it works, and b) the ordering is cached, so the algorithm will only run once per set of handlers.

If you want to know more, or perhaps put RespectOrderDirectivesHandlersFilter to use, you can visit the RespectOrderDirectivesHandlersFilter page on GitHub.

Castle Windsor resolution logic: Handler filters

One of the features I’m looking forward to in the upcoming Castle Windsor 3.0 (“Wawel”) release is handler filters! I’m especially looking forward to this feature because it solves a problem I have had quite a few times now, and also because it’s a feature that I’ve contributed to the Windsor project.

Please note that handler filter are NOT available before Windsor 3.0, which will probably be out sometime around middle August 2011.

As you can see, handler selectors is a hook in Resolve that sorts out the situation by choosing one handler among all the available handlers. Pretty much related to this, are handler filters, which is a hook in ResolveAll, that sorts out the situation by choosing and ordering several handlers from all the available handlers. Let’s take a look at a tiny example….

Example: Task processing pipeline

A golden use case for this feature is when you rely on CollectionResolver to inject a collection for you, e.g. in chain of responsibility-like scenarios like so:

Usually, when doing this kind of task processing, you care about the order in which the tasks are processed. Let’s pretend we have some tasks:

and the tasks are registered “dynamically” (allowing us to add new tasks just by dropping new implementations of ITask into the project), like so:

Now, how do we make sure that the PrepareSomething and FinishTheJob tasks are run at the right time, i.e. before and after CarryItOut? Handler filters to the rescue!

Let’s register a handler filter like so:

and the filter is implemented like this:

Now, when my program does this:

I get this output:

just as expected, which in turn means that CollectionResolver’s call to ResolveAll will also yield an ordered list of tasks.

One could also imagine that only certain handlers were returned, thus allowing tenants in multi-tenant scenarios to have different task processing pipelines.

Nifty, huh? In the next post, I will show a simple yet sophisticated way of ordering the handlers in the SelectHandlers method of a handler filter.

Castle Windsor resolution logic: Handler selectors

Do you know what handler selectors are? It’s a way for you to register some logic in Windsor that will choose among all the available handlers when some particular component is resolved.

E.g. if you have a multi-tenant application with multiple implementations of IUserNotifier, let’s call them NotifyUserBySms and NotifyUserByEmail, and you need to make sure that one particular tenant whose employees are equipped with smartphones get notified by email, you can let a handler selector make this selection transparent to the rest of your application by adding a handler selector, like so:

thus making it possible for all other services to depend on IUserNotifier, not caring under which tenant’s context they’re running.

As you can see, this handler selector only has an opinion when an IUserNotifier is being resolved. And then, when its SelectHandler method is invoked, it gets to choose among all assignable handlers for that particular service type, effectively providing a way to make sure that some particular implementation is used, given some condition (here simulated by some Console.ReadKey() action).

Nifty huh? Only sad thing though, is that handler selectors are not pulled from the container – you have to supply an instance to the kernel, so if you need some services in the selector you need to pull them manually from the container. This can of course be overcome by supplying the handler selector with a reference to the container, allowing it to Resolve stuff at will – just remember – as always – to Release what you Resolve.

This was a short introduction to handler selectors – next post will be about something new, namely handler filters which is a new feature in Windsor 3.0.