Showing posts with label IoC. Show all posts
Showing posts with label IoC. Show all posts

Monday, November 25, 2013

EasyNetQ’s Minimalist DI Container

I’ve been a long time fan of IoC (or DI) containers ever since I first discovered Castle Windsor back in 2007. I’ve used Windsor in every major project I’ve been involved in since then, and if you’d gone to a developer event in the late naughties, you may well have encountered me speaking about Windsor. Indeed, Seb Lambla had the cheek to call me ‘Windsor man’. I shall label him ‘Rest-a-man’ in revenge.

When I started working on EasyNetQ in 2011, I initially thought it would be a very simple lightweight wrapper around the RabbitMQ.Client library. The initial versions were very procedural, ‘just get it done’, script-ish code burps. But as it turned into a more serious library, I started to factor the different pieces into more SRPish classes using dependency injection. At this point I was doing poor-man’s dependency injection, with an initial piece of wire-up code in the RabbitHutch class.

As EasyNetQ started to gain some traction outside 15below, I began to get questions like, “how do I use a different serializer?” And “I don’t like your error handling strategy, how can I implement my own?” I was also starting to get quite bored of maintaining the ever-growing wire up code. The obvious solution was to introduce a DI container, but I was very reluctant to take a dependency on something like Windsor. Writing a library is a very different proposition than writing an application. Every dependency you introduce is a dependency that your user also has to take. Imagine you are a happily using AutoFac and suddenly Castle.Windsor appears in your code base, or even worse, you are an up-to-date Windsor user, but EasyNetQ insists on installing an old version of Windsor alongside. Nasty. Windsor is an amazing library, some of its capabilities are quite magical, but I didn’t need any of these advanced features in EasyNetQ. In fact I could be highly constrained in my DI container requirements:

  • I only needed singleton instances.
  • The lifetime of all DI provided components matches the lifetime of the main IBus interface.
  • I didn’t need the container to manage component disposal.
  • I didn’t need open generic type registration.
  • I was happy to explicitly register all my components, so I didn’t need convention based registration.
  • I only needed constructor injection.
  • I can guarantee that a component implementation will only have a single constructor.

With this highly simplified list of requirements, I realised that I could write a very simple DI container in just few lines of code (currently 113 as it turns out).

My super simple container only provides two registration methods. The first takes a service interface type and a instance creation function:

IServiceRegister Register<TService>(Func<IServiceProvider, TService> serviceCreator) where TService : class;

The second takes an instance type and an implementation type:

IServiceRegister Register<TService, TImplementation>()
where TService : class
where TImplementation : class, TService;

These are both defined in a IServiceRegister interface. There is also a single Resolve method in an IServiceProvider interface:

TService Resolve<TService>() where TService : class;

You can see all 113 lines of the implementation in the DefaultServiceProvider class. As you can see, it’s not at all complicated, just three dictionaries, one holding the list of service factories, another holding a list of registrations, and the last a list of instances. Each registration simply adds a record to the instances dictionary. When Resolve is called, a bit of reflection looks up the implementation type’s constructor and invokes it, recursively calling resolve for each constructor argument. If the service is provided by a service factory, it is invoked instead of the constructor.

I didn’t have any worries about performance. The registration and resolve code is only called once when a new instance of IBus is created. EasyNetQ is designed to be instantiated at application start-up and for that instance to last the lifetime of the application. For 90% of applications, you should only need a single IBus instance.

EasyNetQ’s component are registered in a ComponentRegistration class. This provides an opportunity for the user to register services ahead of the default registration, and since the first to register wins, it provides an easy path for users to replace default services implementations with their own. Here’s an example of replacing EasyNetQ’s default console logger with a custom logger:

var logger = new MyLogger();
var bus = RabbitHutch.CreateBus(connectionString, x => x.Register<IEasyNetQLogger>(_ => logger));

You can replace pretty much any of the internals of EasyNetQ in this way: the logger, the serializer, the error handling strategy, the dispatcher threading model … Check out the ComponentRegistration class to see the whole list.

Of course the magic of DI containers, the first rule of their use, and the thing that some people find extraordinarily hard to grok, is that I only need one call to Resolve in the entire EasyNetQ code base at line 146 in the RabbitHutch class:

return serviceProvider.Resolve<IBus>();

IoC/DI containers are often seen as very heavyweight beasts that only enterprise architecture astronauts could love, but nothing could be more wrong. A simple implementation only needs a few lines of code, but provides your application, or library, with considerable flexibility.

EasyNetQ is open source under the (very flexible) MIT licence. Feel free to cut-n-paste my DefaultServiceProvider class for your own use.

Wednesday, March 18, 2009

WCF / Windsor Integration: Adding Behaviours

Continuing my love fest with the Windsor WCF facility, today I'm going to show you how to add behaviours to your WCF service. Behaviours are the core extension point for WCF and allow you to do pretty much anything with your service. Here's a nice brief description by Mehran Nikoo (it was the first thing that popped up on google :)

The WCF Facility automatically discovers any registered WCF behaviours and adds them to the service. The really nice thing about this is that because the behaviours are also IoC hosted components, the container can automatically provide their dependencies just like any other component. If you need to use any of your services inside the behaviour, simply inject it through the constructor as normal.

Let's look at an example where we want to log the entry and exit from an operation. Here's a simple service:

[ServiceContract]
public interface IHelloService
{
    [OperationContract]
    string Hello(string name);
}
public class HelloService : IHelloService
{
    private readonly ILogger logger;
    public HelloService(ILogger logger)
    {
        this.logger = logger;
    }
    public string Hello(string name)
    {
        logger.WriteLine("In Hello()");
        return string.Format("Hello {0}", name);
    }
}

It has a single operation 'Hello' that takes a name and returns 'Hello <name>'. It also has a dependency on ILogger which it uses to log that the Hello operation has been invoked.

Now lets create a WCF behaviour:

public class TestEndpointBehaviour : IEndpointBehavior
{
    private readonly TestCallContextInitializer callContextInitializer;
    public TestEndpointBehaviour(TestCallContextInitializer callContextInitializer)
    {
        this.callContextInitializer = callContextInitializer;
    }
    public void Validate(ServiceEndpoint endpoint){}
    public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters){}
    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime){}
    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
    {
        foreach (var operation in endpointDispatcher.DispatchRuntime.Operations)
        {
            operation.CallContextInitializers.Add(callContextInitializer);
        }
    }
}

We want to write to the logger before and after every operation invocation, to do that we're creating an Endpoint behaviour. The Endpoint behaviour gives you an opportunity, the ApplyDispatchBehaviour method, to add a 'CallContextInitializer' that can intercept operation invocations.  Note that we resolve our CallContextInitializer from the IoC container by expecting it to be injected via a constructor parameter.

As an aside, I can't help feeling that the WCF behaviour API is overly complex, it hardly invites you in :) There's no way I would have worked out how to do this without looking at the documentation. Not at all the pit of success.

Rant over, here's our CallContextInitializer:

 

public class TestCallContextInitializer : ICallContextInitializer
{
    private readonly ILogger logger;
    public TestCallContextInitializer(ILogger logger)
    {
        this.logger = logger;
    }
    public object BeforeInvoke(InstanceContext instanceContext, IClientChannel channel, Message message)
    {
        logger.WriteLine("Before Invoke");
        return null;
    }
    public void AfterInvoke(object correlationState)
    {
        logger.WriteLine("After Invoke");
    }
}

The ICallContextInitializer interface has two methods: BeforeInvoke and AfterInvoke where which allow us to execute any actions before and after the operation is invoked. Here we're just using the logger to write some interesting stuff out. Note that because the TestCallContextInitializer is also an IoC component we can resolve any of our services as constructor arguments again. Here we using the same ILogger service that our HelloService uses.

Here's the configuration and a little test to show it all working:

[TestFixture]
public class WCFIntegration_Spikes
{
    private const string tcpEndpointAddress = "net.tcp://localhost:4321/HelloService";
    [SetUp]
    public void SetUp()
    {
    }
    [Test, Explicit]
    public void Simple_TCP_Service()
    {
        var container = new WindsorContainer()
            .AddFacility<WcfFacility>()
            .Register(
                Component.For<ILogger>().ImplementedBy<Logger>(),
                Component.For<TestCallContextInitializer>(),
                Component.For<TestEndpointBehaviour>(),
                Component.For<IHelloService>().ImplementedBy<HelloService>()
                    .ActAs(new DefaultServiceModel().AddEndpoints(
                        WcfEndpoint.BoundTo(new NetTcpBinding { PortSharingEnabled = false }).At(tcpEndpointAddress)
                    ))
            );
        var client = ChannelFactory<IHelloService>.CreateChannel(
            new NetTcpBinding { PortSharingEnabled = false }, new EndpointAddress(tcpEndpointAddress));
        Console.WriteLine(client.Hello("Mike"));
        container.Dispose();
    }                
}

We first register the WcfFacility as usual. Then we register our components. Note that we don't need to do any special configuration for our EndpointBehaviour, the WCF Facility takes care of this for us.

When we run the test we get this output to the console:

Before Invoke
In Hello()
After Invoke
Hello Mike

As expected our behaviour was installed and invoked.

Integrating WCF and Windsor like this provides a very slick way of doing web services. I'm very impressed with Craig Neuwirt's work, what a star. Shame he doesn't blog more about it.

Monday, March 09, 2009

Castle Windsor: Registering and resolving arrays of dependencies using the fluent registration API

The Castle Windsor fluent registration API is a powerful and beautiful thing, but it's very new and the documentation is still evolving. Mostly I find the best thing is just to read the code, especially the unit tests. Today I wanted to register an array of components that all implement the same interface, and then resolve them in a particular order for another component that expects an array of that interface in its constructor.

Here's how it's done. First lets define an interface and some types that implement it:

public interface IMyInterface { }
public class MyFirstThing : IMyInterface {}
public class MySecondThing : IMyInterface {}
public class MyThirdThing : IMyInterface {}

Then we have a component that has a dependency on IMyInterface:

public class HasArrayDependency
{
    private readonly IMyInterface[] myInterfaces;
    public HasArrayDependency(IMyInterface[] myInterfaces)
    {
        this.myInterfaces = myInterfaces;
    }
    public IMyInterface[] MyInterfaces
    {
        get { return myInterfaces; }
    }
}

Here's a test showing the registration:

[Test]
public void Demonstrate_fluent_registration_of_arrays()
{
    var container = new WindsorContainer()
        .Register(
            Component.For<HasArrayDependency>()
                .ServiceOverrides(
                    ServiceOverride.ForKey("myInterfaces").Eq(
                        "MyFirstThing",
                        "MySecondThing",
                        "MyThirdThing"
                    )
                ),
            AllTypes
                .FromAssembly(Assembly.GetExecutingAssembly())
                .BasedOn<IMyInterface>()
                    .WithService.FromInterface(typeof(IMyInterface))
                    .Configure(c => c.Named(c.Implementation.Name))
        );
    var hasArrayDependency = container.Resolve<HasArrayDependency>();
    Assert.That(hasArrayDependency.MyInterfaces[0].GetType().Name, Is.EqualTo("MyFirstThing"));
    Assert.That(hasArrayDependency.MyInterfaces[1].GetType().Name, Is.EqualTo("MySecondThing"));
    Assert.That(hasArrayDependency.MyInterfaces[2].GetType().Name, Is.EqualTo("MyThirdThing"));
}

There are a couple of things we need to do. If we simply register components like this:

var container = new WindsorContainer()
    .Register(
        AllTypes
            .FromAssembly(Assembly.GetExecutingAssembly())
    );

By default they will be named with their full type name rather than just the class name, so we have to use the Configure method with the lambda expression to change the component name to the class name.

Next we use the ServiceOverrides method to override the default dependency resolution. Here we are saying that for the constructor parameter named 'myInterfaces' we are going to supply the components named 'MyFirstThing', 'MySecondThing', and 'MyThirdThing'. Castle Windsor doesn't provide array parameters with any service of the array type by default, if you want that behaviour you need to use a custom sub dependency resolver as described here.

Friday, January 30, 2009

Further Reading on IoC Containers

Eric Nelson was kind enough to invite me to contribute to the MSDN Flash newsletter. It should be published next Wednesday. The article was limited to 500 words, only enough for a very brief introduction to IoC containers, so for those who want to explore this exciting topic further, here are some links:

Oren Eini's (AKA Ayende) MSDN article: Inversion of Control and Dependency Injection: Working with Windsor Container:

http://msdn.microsoft.com/en-us/library/aa973811.aspx

Hamilton Verissimo's Code Project article: Introducing Castle - Part 1:

http://www.codeproject.com/KB/architecture/introducingcastle.aspx

The first chapter of Dhanji R. Prasanna's new book on Dependency Injection:

http://www.manning.com/prasanna/prasanna_meapch1.pdf

 

Some popular IoC containers for .NET:

Castle Windsor. This one is probably the most popular, I'm biased though since it's the one I use. It was originally written by Hamilton Verissimo (who now works on the MEF team) and maintained is by Ayende.

StructureMap. Also very highly regarded. It's author, Jeremy Miller, has an excellent blog.

Spring.NET. A port of the popular Java Spring container.

Ninject and Autofac are both interesting newcomers.

Unity is from the Microsoft Patterns and Practices group.

Glen Block will kill me, but MEF is also an IoC container, although one that's specifically targeted at developing plug-in application architectures.

Friday, November 28, 2008

Multi-tenancy part 2: Components and Context

In my previous post, Multi-tenancy part 1: Strategy, I talked about some of the high level decisions we have to make when building a single software product for multiple users with diverse requirements. Today I'm going to look at implementing basic multi-tenancy with Suteki Shop. I'm going to assume that my customers have identical functional requirements, but will obviously need to have separate styles and databases. Some other simple configurable items will also be different, such as the name of their company and their contact email address.

But first I want to suggest something that's become quite clear as I've started to think more about implementing multi-tenancy. I call it:

Hadlow's first law of multi-tenancy: A multi-tenanted application should not look like a multi-tenanted application.

What do I mean by this? The idea is that you should not have to change your existing single-tenant application in any way in order to have it serve multiple clients. If you build your application using SOLID principles, if you architect it as a collection of components using Dependency Injection and an IoC container, then you should be able to compose the components at runtime based on some kind of user context without changing the components themselves.

I am going to get Suteki Shop to serve two different tenants without changing a single existing line of of (component) code.

We are going to be serving two clients. The first one is our existing client, the mod-tastic Jump the Gun. I've invented the new client zanywear.com. I just made the name up, it's actually a registered domain name but it's not being used. We're going to serve our clients from the same application instance, so we create a new web site and point it to an instance of Suteki Shop. Now we configure two host headers (AKA Site Bindings) for the web application:

test.jumpthegun.co.uk
zanywear.com

multitenanted-iis

For testing purposes (and because I don't own zanywear.com :) I've added the two domains to my C:\WINDOWS\system32\drivers\etc\hosts file so that it looks like this:

# Copyright (c) 1993-1999 Microsoft Corp.
#
# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.
#
# This file contains the mappings of IP addresses to host names. Each
# entry should be kept on an individual line. The IP address should
# be placed in the first column followed by the corresponding host name.
# The IP address and the host name should be separated by at least one
# space.
#
# Additionally, comments (such as these) may be inserted on individual
# lines or following the machine name denoted by a '#' symbol.
#
# For example:
#
#      102.54.94.97     rhino.acme.com          # source server
#       38.25.63.10     x.acme.com              # x client host
127.0.0.1     localhost
127.0.0.1     test.jumpthegun.co.uk
127.0.0.1     zanywear.com

Now when I browse to test.jumpthegun.co.uk or zanywear.com I see the Jump the Gun website.

The task now is to choose a different database, style-sheet and some basic configuration settings when the HTTP request's host name is zanywear.com. Conventiently Suteki Shop has two services that define these items. The first is IConnectionStringProvider which provides (you guessed it) the database connection string:

namespace Suteki.Common.Repositories
{
    public interface IConnectionStringProvider
    {
        string ConnectionString { get; }
    }
}

And the other is the somewhat badly named IBaseControllerService that supplies some repositories and config values to be consumed by the master view:

using Suteki.Common.Repositories;
namespace Suteki.Shop.Services
{
    public interface IBaseControllerService
    {
        IRepository<Category> CategoryRepository { get; }
        IRepository<Content> ContentRepository { get; }
        string GoogleTrackingCode { get; set; }
        string ShopName { get; set; }
        string EmailAddress { get; set; }
        string SiteUrl { get; }
        string MetaDescription { get; set; }
        string Copyright { get; set; }
        string PhoneNumber { get; set; }
        string SiteCss { get; set; }
    }
}

Note that this allows us to to set the name of the style-sheet and some basic information about the shop.

In order to choose which component is used to satisfy a service at runtime we use an IHandlerSelector. This interface was recently introduced to the Windsor IoC container by Oren Eini (AKA Ayende Rahien) specifically to satisfy the requirements of multi-tenanted applications. You need to compile the trunk if you want to use it. It's not in the release candidate. It looks like this:

using System;
namespace Castle.MicroKernel
{
    /// <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);
    }
}

The comments are self explanatory. I've implemented the interface as a HostBasedComponentSelector that can choose components based on the HTTP request's SERVER_NAME value:

using System;
using System.Linq;
using System.Web;
using Castle.MicroKernel;
using Suteki.Common.Extensions;
namespace Suteki.Common.Windsor
{
    public class HostBasedComponentSelector : IHandlerSelector
    {
        private readonly Type[] selectableTypes;
        public HostBasedComponentSelector(params Type[] selectableTypes)
        {
            this.selectableTypes = selectableTypes;
        }
        public bool HasOpinionAbout(string key, Type service)
        {
            foreach (var type in selectableTypes)
            {
                if(service == type) return true;
            }
            return false;
        }
        public IHandler SelectHandler(string key, Type service, IHandler[] handlers)
        {
            var id = string.Format("{0}:{1}", service.Name, GetHostname());
            var selectedHandler = handlers.Where(h => h.ComponentModel.Name == id).FirstOrDefault() ??
                                  GetDefaultHandler(service, handlers);
            return selectedHandler;
        }
        private IHandler GetDefaultHandler(Type service, IHandler[] handlers)
        {
            if (handlers.Length == 0)
            {
                throw new ApplicationException("No components registered for service {0}".With(service.Name));
            }
            return handlers[0];
        }
        protected string GetHostname()
        {
            return HttpContext.Current.Request.ServerVariables["SERVER_NAME"];
        }
    }
}

It works like this: It expects an array of types to be supplied as constructor arguments. These are the service types that we want to choose based on the host name. The HasOpinionAbout method simply checks the supplied serivce type against the array of types and returns true if there are any matches. If we have an opinion about a service type the container will ask the IHandlerSelector to supply a handler by calling the SelectHandler method. We create an id by concatenating the service name with the host name and then return the component that's configured with that id. So the configuration for Jump the Gun's IConnectionStringProvider will look like this:

<component
  id="IConnectionStringProvider:test.jumpthegun.co.uk"
  service="Suteki.Common.Repositories.IConnectionStringProvider, Suteki.Common"
  type="Suteki.Common.Repositories.ConnectionStringProvider, Suteki.Common"
  lifestyle="transient">
  <parameters>
    <ConnectionString>Data Source=.\SQLEXPRESS;Initial Catalog=JumpTheGun;Integrated Security=True</ConnectionString>
  </parameters>
</component>

Note the id is <name of service>:<host name>.

The configuration for Zanywear looks like this:

<component
  id="IConnectionStringProvider:zanywear.com"
  service="Suteki.Common.Repositories.IConnectionStringProvider, Suteki.Common"
  type="Suteki.Common.Repositories.ConnectionStringProvider, Suteki.Common"
  lifestyle="transient">
  <parameters>
    <ConnectionString>Data Source=.\SQLEXPRESS;Initial Catalog=Zanywear;Integrated Security=True</ConnectionString>
  </parameters>
</component>

Note that you can have multiple configurations for the same service/component in Windsor so long as ids are different.

When the host name is test.jumpthegun.co.uk the HostBasedComponentSelector will create a new instance of ConnectionStringProvider with a connection string that points to the JumpTheGun database. When the host name is zanywear.com it will create a new instance of ConnectionStringProvider with a connection string that points to the Zanywear database. We configure our IBaseControllerService in a similar way.

The only thing left to do is register our IHandlerSelector with the container. When I said I didn't have to change a single line of code I was telling a fib, we do have to change the windsor initialization to include this:

protected virtual void InitializeWindsor()
{
    if (container == null)
    {
        // create a new Windsor Container
        container = new WindsorContainer(new XmlInterpreter("Configuration\\Windsor.config"));
        // register handler selectors
        RegisterHandlerSelectors(container);
        // register WCF integration
        RegisterWCFIntegration(container);
        // automatically register controllers
        container.Register(AllTypes
            .Of<Controller>()
            .FromAssembly(Assembly.GetExecutingAssembly())
            .Configure(c => c.LifeStyle.Transient.Named(c.Implementation.Name.ToLower())));
        // set the controller factory to the Windsor controller factory (in MVC Contrib)
        System.Web.Mvc.ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(container));
    }
}
/// <summary>
/// Get any configured IHandlerSelectors and register them.
/// </summary>
/// <param name="windsorContainer"></param>
protected virtual void RegisterHandlerSelectors(IWindsorContainer windsorContainer)
{
    var handlerSelectors = windsorContainer.ResolveAll<IHandlerSelector>();
    foreach (var handlerSelector in handlerSelectors)
    {
        windsorContainer.Kernel.AddHandlerSelector(handlerSelector);
    }
}

The handler selector setup occurs in the RegisterHandlerSelectors method. We simply ask the container to resolve any configured IHandlerSelectors and add them in. The configuration for our HostBasedComponentSelector looks like this:

<component
  id="urlbased.handlerselector"
  service="Castle.MicroKernel.IHandlerSelector, Castle.MicroKernel"
  type="Suteki.Common.Windsor.HostBasedComponentSelector, Suteki.Common"
  lifestyle="transient">
  <paramters>
    <selectableTypes>
      <array>
        <item>Suteki.Shop.Services.IBaseControllerService, Suteki.Shop</item>
        <item>Suteki.Common.Repositories.IConnectionStringProvider, Suteki.Common</item>
      </array>
    </selectableTypes>
  </paramters>
</component>

Note that we are configuring the list of services that we want to be selected by the HostBasedHandlerSelector by using the array parameter configuration syntax.

And that's it. We now have a single instance of Suteki Shop serving two different clients: Jump the Gun and Zanywear.

multitenanted-websites

Today I've demonstrated the simplest case of multi-tenanting. It hardly qualifies as such because our two tenants both have identical requirements. The core message here is that we didn't need to change a single line of code in any of our existing components. You can still install Suteki Shop and run it as a single-tenant application by default.

In the next installment I want to show how we can provide different implementations of components using this approach. Later I'll deal with the more complex problem of variable domain models. Watch this space!

Tuesday, November 25, 2008

Windsor WCF Integration

I've been playing with the Windsor WCF Integration facility today. I've been using a recent trunk build of the Castle project, and since there's been a lot of work recently on the WCF facility, the docs on the Castle site are somewhat out of date. I had to work out how to use the facility by reading the unit tests and a post by Craig Neuwirt to the Castle Project Development list.

So why would you want to integrate WCF with your IoC container? When you use an IoC container in your application it should be the repository of any service that you consume. The service consumer should not care about how the service is implemented or where it comes from. A service should also not be concerned about how it is consumed. The Windsor WCF facility allows you to use your WCF services and proxies as if they were any other service provided by the container.

Let's think about how this might help us when writing enterprise applications. My eCommerce platform, Suteki Shop, sends the customer an email confirming that they've made an order. It sends them another email when the order is dispatched. I have an interface IEmailSender that defines the contract for sending an email. Currently my Windsor configuration maps the IEmailSender service to a class called EmailSender. The OrderController expects to be given an instance of IEmailSender in its constructor. So now it gets an actual instance of EmailSender that wraps the .NET API for sending emails. When the customer clicks the 'order' button the request blocks while an email is sent. This isn't a very scalable solution, but I'm not worried about it now because the only client I have for Suteki Shop is low volume. If their shop take off and starts to get a lot more traffic, I will want to have a more scalable architecture for sending emails. With the WCF integration I could configure IEmailSender to provide a WCF proxy instead of a concrete class. I could then install EmailSender (the IEmailSender implementation) on another server and configure the local container to expose it as a WCF service. The protocol I use can be configured using WCF. So I could use TCP, SOAP, MSMQ, or whatever fitted the purpose. The key point is that by using the WCF facility I've been able to take a part of my application and move to to a new process or machine without touching a single line of code.

So how do you use the WCF facility?

Service

Let's assume we have a simple service interface:

[ServiceContract(Namespace = "Mike.WindsorWCFIntegration")]
public interface ICustomerService
{
    [OperationContract]
    Customer GetCustomer(int id);        
}

Customer is just some entity in my application. In order to serve this via WCF we have to attribute the service interface with WCF attributes: ServiceContract and OperationContract. We don't have to do anything to the existing Windsor.config file, it looks the same as before:

<component id="customerService"
   service="Mike.WindsorWCFIntegration.ICustomerService, Mike.WindsorWCFIntegration"
   type="Mike.WindsorWCFIntegration.DefaultCustomerService, Mike.WindsorWCFIntegration">
</component>

We're telling the container that when a component asks for an ICustomerService (or 'customerService' by name) they will be given DefaultCustomerService. Since I'm going to host the service as part of a web application, we can use the WCF IIS integration and create a CustomerService.svc file for the customer service that defines the service host:

<%@ ServiceHost Language="C#" Service="customerService" 
Factory="Castle.Facilities.WcfIntegration.DefaultServiceHostFactory, Castle.Facilities.WcfIntegration"  %>

Note that the Service attribute specifies the same name as the component id in the Windsor.config. The other important point is that we're asking WCF to use the Castle DefaultServiceFactory. This service factory wraps the Windsor container which it uses to resolve any service requests.

We configure WCF as normal:

<system.serviceModel>
  <services>
    <service name="customerService">
      <endpoint contract="Mike.WindsorWCFIntegration.ICustomerService" binding="basicHttpBinding" />
    </service>
  </services>
</system.serviceModel>

Finally we have to register the WCF Facility with the container on application start:

protected void Application_Start(object sender, EventArgs e)
{
    Container = new WindsorContainer()
        .AddFacility<WcfFacility>()
        .Install(Configuration.FromXmlFile("Windsor.config"));
}

The nice thing is that we haven't had to alter our Windsor.configuration or our existing service. Although we did have to attribute our service interface with WCF specific concerns which is a bit of a shame.

Client

The client side story is also pretty simple. Here's a client service that uses the customerService:

using System;
namespace Mike.WindsorWCFIntegration.Client
{
    public class DoSomethingWithCustomers : IDoSomethingWithCustomers
    {
        private readonly ICustomerService customerService;
        public DoSomethingWithCustomers(ICustomerService customerService)
        {
            this.customerService = customerService;
        }
        public void DoIt()
        {
            WriteClientDetails(customerService);
            WriteClientDetails(customerService);
        }
        private static void WriteClientDetails(ICustomerService customerService)
        {
            var customer = customerService.GetCustomer(24);
            ...
        }
    }
}

It's expecting the customerService to be injected by the container. The Windsor.config has to specify that ICustomerService is provided by WCF:

<component id="customerService"
    type="Mike.WindsorWCFIntegration.ICustomerService, Mike.WindsorWCFIntegration"
    wcfEndpointConfiguration="customerClient">
</component>

The wcfEndpointConfiguration references the WCF configuration in App.config, note that it's the same as the endpoint name, 'customerClient':

<configuration>
  <system.serviceModel>
    <client>
      <endpoint address="http://localhost:2730/CustomerService.svc"
        binding="basicHttpBinding"
        contract="Mike.WindsorWCFIntegration.ICustomerService"
        name="customerClient">
      </endpoint>
    </client>
  </system.serviceModel>
</configuration>

Once again we have to make sure that the WCF Facility is registered with the container (you can do this in the XML configuration as well):

var container = new WindsorContainer()
 .AddFacility<WcfFacility>()
 .Install(Configuration.FromXmlFile("Windsor.config"));

I hope I've been able to show that using WCF integration with Windsor can be a big win in extending component oriented application design to include serving and consuming remote services. Note that in none of the code above did I have to change the implementation of any of my services in order to make them work with WCF. You can retain your Dependency Injected, testable components and simply have them served onto the web. WCF allows you to configure the wire format (SOAP, REST, POX, binary) and transport (HTTP, named pipes, TCP-IP) independently of your component design. It's very easy to use and very nifty.

You can download the complete demo solution here:

http://static.mikehadlow.com/Mike.WindsorWCFIntegration.zip