Posted by & filed under .Net.

If you recall when configuring the container via xml you can do a
service override like so:



    
        

        

        

            
                ${smtp.sender}
            

        

    

Check out the documentation on the
castle site
for some more details.

I recently got an email question around how to do this with the
fluent interface – unfortunately with the XML, Binsor and Fluent
interfaces all being used for registering and configuring the
MicroKernel/Windsor Container the documentation is a little patchy
across all three (with XML of course having the best coverage) – so
here’s an example of service override for the fluent
interface.

First off the various services we’ll be wiring up in this
example.

public interface IStaffService
{
}

public class StaffService : IStaffService
{
  public IStaffRepository Repository { get; set; }
}

public interface IStaffRepository
{
}

public class StaffRepositoryA : IStaffRepository
{
}

public class StaffRepositoryB : IStaffRepository
{
}

And now the actual tests..

public class ServiceOverrideTests
{
  private WindsorContainer container;

  public ServiceOverrideTests()
  {
    container = new WindsorContainer();      
    container.Register(Component.For<IStaffRepository>().Named("repository.staff.a").ImplementedBy<StaffRepositoryA>().LifeStyle.Transient);
    container.Register(Component.For<IStaffRepository>().Named("repository.staff.b").ImplementedBy<StaffRepositoryB>().LifeStyle.Transient);
  }

  [Fact]
  public void ByDefaultStaffServiceWiredUpToFirstServiceRegistered()
  {
    container.Register(Component.For<IStaffService>().Named("service.staff").ImplementedBy<StaffService>().LifeStyle.Transient);

    var staffService = (StaffService)container.Resolve<IStaffService>();

    Assert.IsType<StaffRepositoryA>(staffService.Repository);      
  }    

  [Fact]
  public void WithServiceOverrideCanPickImplmentationByKey()
  {
    container.Register(Component.For<IStaffService>().Named("service.staff").ImplementedBy<StaffService>()
                         .ServiceOverrides(ServiceOverride.ForKey("Repository").Eq("repository.staff.b")).LifeStyle.Transient);

    var staffService = (StaffService)container.Resolve<IStaffService>();

    Assert.IsType<StaffRepositoryB>(staffService.Repository);   
  }
}

With
.ServiceOverrides(ServiceOverride.ForKey(“Repository”).Eq(“repository.staff.b”))
being the code we’re interested in… obviously if it was a
constructor override we’d be using the name of the parameter in the
constructor.

The Eq method can also take of an array of strings… which,
you guessed it, means we can handle arrays of services as well …
which can be quite handy if order is important to some kind of
service you’re building where there are multiple contributors or
some form of pipeline, lets take a look at that:

public class StaffService : IStaffService
{
  public IStaffRepository[] Repositories { get; set; } // <- is now an array of staff repository...
}

And the associated test – notice we just pass in a list of the
service names…

[Fact]
public void WithServiceOverrideCanPickImplmentationByKey()
{
  container.Register(Component.For<IStaffService>().Named("service.staff").ImplementedBy<StaffService>()
                       .ServiceOverrides(ServiceOverride.ForKey("Repositories").Eq("repository.staff.b", "repository.staff.a")).LifeStyle.Transient);

  var staffService = (StaffService)container.Resolve<IStaffService>();

  Assert.IsType<StaffRepositoryB>(staffService.Repositories[0]);
  Assert.IsType<StaffRepositoryA>(staffService.Repositories[1]);
}

Hopefully this proves useful to Jason (who sent me the email) and
anyone else who’s getting started with windsor and strugling a
little to setup their container.

One Response to “Service overrides when using Windsor Fluent Component Registration”

  1. Alex Henderson

    Hmmm…

    I’m not a fan of that registration code myself for services, the first interface is very hit and miss and wouldn’t be immediately obvious to someone refactoring the code that introducing an additional interface could disrupt just what service the component is mapped to (because order isn’t guaranteed)… plus I can’t help but feel that an IService marker interface is a code smell, better handled through the use of a class attribute.

    That said if I was going to use a class attribute to mark services I’d probably just go the whole hog and use the CastleComponentAttribute, allowing me to specify a service type, key and lifestyle for each service- though at that point you’re not really gaining anything.

    Another approach might be to just use an attribute like [Component] to mark classes that need registering, and then decorating the service with an attribute like [Service] so your registration code could correctly pick the first "service" interface implemented by the component, rather then just the first service… this avoids some repetition (and obviously DRY == good).

    All that said your approach is certainly concise, and the less component registration code you need to maintain the better! though for me I’m not sure how well it would work out i.e. I tend to make use of generic repositories and decorator chains quite often, and obviously order of registration etc. is important in these cases, so I generally need to be quite explicit about what I register.