Ayende @ Rahien

My name is Oren Eini
Founder of Hibernating Rhinos LTD and RavenDB.
You can reach me by phone or email:


+972 52-548-6969

, @ Q c

Posts: 6,026 | Comments: 44,842

filter by tags archive

Windsor - IHandlerSelector

time to read 3 min | 527 words

In my previous post I introduced the basis of context as an architectural pattern. Now I want to talk about how we can implement that using Windsor and a new extensibility point: IHandlerSelector.

The interface is defined as:

/// <summary>
/// Implementors of this interface allow to extend the way the container perform
/// component resolution based on some application specific business logic.
/// </summary>
/// <remarks>
/// This is the sibling interface to <seealso cref="ISubDependencyResolver"/>.
/// This is dealing strictly with root components, while the <seealso cref="ISubDependencyResolver"/> is dealing with
/// dependent components.
/// </remarks>
public interface IHandlerSelector
    /// <summary>
    /// Whatever the selector has an opinion about resolving a component with the 
    /// specified service and key.
    /// </summary>
    /// <param name="key">The service key - can be null</param>
    /// <param name="service">The service interface that we want to resolve</param>
    bool HasOpinionAbout(string key, Type service);

    /// <summary>
    /// Select the appropriate handler from the list of defined handlers.
    /// The returned handler should be a member from the <paramref name="handlers"/> array.
    /// </summary>
    /// <param name="key">The service key - can be null</param>
    /// <param name="service">The service interface that we want to resolve</param>
    /// <param name="handlers">The defined handlers</param>
    /// <returns>The selected handler, or null</returns>
    IHandler SelectHandler(string key, Type service, IHandler[] handlers);

And registering it in the container is simply:


A handler selector is asked if it wants to express an opinion on a particular component resolution, based on key (optional) and type. Assuming we say yes, we are called to select the appropriate handler from all the registered handlers that can satisfy that request.

Let us say that we want to recover from the database being down by serving an implementation that reads from only the cache, we can implement it thusly:

public class DataAccessHandlerSelector : IHandlerSelector
	bool databaseIsDown = false;

	public DataAccessHandlerSelector()
		DatabaseMonitor.OnChangedState += 
			state => databaseIsDown = state == DatabaseState.Down;

	public bool HasOpinionAbout(string key, Type service)
		return databaseIsDown && service == typeof(IRepository);

	public IHandler SelectHandler(string key, Type service, IHandler[] handlers)
		return handlers.Where(x=>x.ComponentModel.Implementation == typeof(CacheOnlyRepository)).First();


Now we automatically replace, based on our own logic and the current context what type of component the container should resolve.

I am giving the example of detecting infrastructure change, but as important, and as interesting, is the ability to easily use this in order to select services in a multi tenant environment. We can use this approach to perform service overrides all over the place in a way that is natural, easy and extremely powerful.

Have fun...


Tim Scott

How did you know I was just wrestling with this issue? I solved it by creating my own selector which returns a concrete instance based on context. It certainly works but has a smell to it.

I am using Binsor. If this is "new" in Windsor, I suppose it is not, as of today, supported by Binsor? I wonder how hard it would be to add it?

Ayende Rahien

It is not in the Rhino Tools repository, but you can just update the reference it and it will work

Tim Scott

What would be the Binsor equivalent for container.Kernel.AddHandlerSelector(selector)?

Ayende Rahien

Something like:

IoC.Kernel.AddHandlerSelector ( )

Complex, isn't it ?

Comment preview

Comments have been closed on this topic.


No future posts left, oh my!


  1. Technical observations from my wife (3):
    13 Nov 2015 - Production issues
  2. Production postmortem (13):
    13 Nov 2015 - The case of the “it is slow on that machine (only)”
  3. Speaking (5):
    09 Nov 2015 - Community talk in Kiev, Ukraine–What does it take to be a good developer
  4. Find the bug (5):
    11 Sep 2015 - The concurrent memory buster
  5. Buffer allocation strategies (3):
    09 Sep 2015 - Bad usage patterns
View all series


Main feed Feed Stats
Comments feed   Comments Feed Stats