Saturday, September 06, 2008
If you recall when configuring the container via xml you can do a service override like so:

<configuration>

 

    <components>

        <component id="smtp.sender"

            service="Namespace.IEmailSender, AssemblyName"

            type="Namespace.SmtpMailSender, AssemblyName" />

 

        <component id="sendmail.sender"

            service="Namespace.IEmailSender, AssemblyName"

            type="Namespace.SendMailEmailSender, AssemblyName" />

 

        <component id="newsletter"

            type="Namespace.NewsLetterSenderService, AssemblyName">

 

            <parameters>

                <sender>${smtp.sender}</sender>

            </parameters>

 

        </components>

 

    </components>

 

</configuration>


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.
posted @ Friday, September 05, 2008 8:29:15 PM (New Zealand Standard Time, UTC+12:00)    Comments [4] | Trackback | Tracked by:
"Avoiding strings in your Windsor fluent config" (Bitter Coder) [Trackback]
Search
FeedCount

Tags...
Who am I?
Alex Henderson
Alex Henderson
Auckland, New Zealand
Managing Director at Dev|Defined Limited

"Self Confessed Coding Junky for 15 years"
View Alex Henderson's profile on LinkedIn
 
Mobile: +64-21-402-969
Email: bittercoder 'at' gmail 'dot' com
MSN: bittercoder_nz@hotmail
Skype: alex.devdefined
Navigation