Mr Andersson

Switching component implementations in Castle Windsor

leave a comment »

Problem: Test suite for a system for which I need to replace (inject) the behavior of a certain component. The system is using Castle Windsor with an XML configuration file.

In this system integration test I want to use the real container configuration except that I want to switch out a component that does authorization using a database.

The replacement for the real component is as simple as:


public bool IUsernamePasswordVerifier.VerifyPasswordFor( string username, string password )
{
return true;
}
Solution: Tried this, which failed on me. But with a little help from a tiny facility used by the test suite I can now “re-wire” service implementations in the container.
There are probably several other solutions on how one could accomplish the same thing, but this one worked out very well for me.

ComponentRewriterFacility.cs:


using System;
using System.Collections.Generic;
using Castle.Core;
using Castle.Core.Configuration;
using Castle.MicroKernel;

namespace ServiceTests.Service
{
public class ComponentRewriteFacility : IFacility
{
readonly IDictionary<Type, Type> _rewrites;

public ComponentRewriteFacility()
{
_rewrites = new Dictionary<Type, Type>();
}

public void AddRewrite<I, T>() where T : I
{
_rewrites.Add( typeof(I), typeof(T) );
}

public virtual void Init( IKernel kernel, IConfiguration facilityConfig )
{
if( kernel == null )
throw new ArgumentNullException( "kernel" );
kernel.ComponentRegistered += ComponentRegistered;
}

public void Terminate()
{
}

void ComponentRegistered( string key, IHandler handler )
{
if( !ShouldRewrite( handler.ComponentModel ) )
return;
handler.ComponentModel.Implementation = _rewrites[handler.ComponentModel.Service];
}

protected virtual bool ShouldRewrite( ComponentModel componentModel )
{
return _rewrites.ContainsKey( componentModel.Service );
}
}
}

And in our test suite initializer we add the “re-write rule” like this:


IWindsorContainer container = new WindsorContainer();
container.AddFacility<ComponentRewriteFacility>( f => f.AddRewrite<IUsernamePasswordVerifier, AnythingGoesUsernamePasswordVerifier>() );
container.AddFacility<WcfFacility>();
container.Install( Castle.Windsor.Installer.Configuration.FromXmlFile( "Windsor.xml" ) );

Like it? Not? Have a better solution? Please let me know!
About these ads

Written by anderssonjohan

October 28, 2009 at 19:34

Posted in programming

Tagged with , , , ,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: