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!
Advertisement

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:

Gravatar
WordPress.com Logo

Please log in to WordPress.com to post a comment to your blog.

Twitter picture

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

Facebook photo

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

Connecting to %s

Follow

Get every new post delivered to your Inbox.