Resolving wcf service instances with an IoC container


In wcf, services are created and disposed by the wcf runtime through an IInstanceProvider implementation. The default implementation calls the parameterless constructor of the service. The easiest way to provide our own IInstanceProvider is to add a behavior to our service host by using an IServiceBehavior.

We can achieve our goal as simple as this:

public sealed class IoCInstanceProvider : IInstanceProvider
{
    private readonly Type serviceType;

    public IoCInstanceProvider(Type serviceType)
    {
        this.serviceType = serviceType;
    }

    public object GetInstance(InstanceContext instanceContext)
    {
        return GetInstance(instanceContext, null);
    }
    public object GetInstance(InstanceContext instanceContext, Message message)
    {
        return IoC.Current.Container.Resolve(this.serviceType);
    }
    public void ReleaseInstance(System.ServiceModel.InstanceContext instanceContext, object instance)
    {
        if (instance is IDisposable)
            (instance as IDisposable).Dispose();
    }
}

The IoC class is just a singleton I use that exposes an Inversion of Control container like Unity.

The IoCInstanceProvider can be used in an existing service by applying an IServiceBehavior to that service through its ServiceHost. The following class shows how we can do this:

public sealed class IoCServiceHostBehavior : IServiceBehavior 
{
    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
        foreach (var channelDispatcherBase in serviceHostBase.ChannelDispatchers)
        {
            var channelDispatcher = channelDispatcherBase as ChannelDispatcher;
            if (channelDispatcher != null)
            {
                foreach (var endpointDispatcher in channelDispatcher.Endpoints)
                {
                    endpointDispatcher.DispatchRuntime
                                      .InstanceProvider = new IoCInstanceProvider(serviceDescription.ServiceType);
                }
            }
        }
    }
    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
    {

    }
    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {

    }
}

The ApplyDispatchBehavior method ensures that for every endpoint provided by the service host for a given serviceDescription, the InstanceProvider used to create the service by the wcf runtime is our own IoCInstanceProvider.

Now we create our own ServiceHost class and make sure we add this behavior before the service host gets opened (if we don’t, the behavior will not get applied).

public class IoCServiceHost : ServiceHost
{
    public IoCServiceHost(Type svcType, params Uri[] baseAddresses)
        : base(svcType, baseAddresses) { }

    public IoCServiceHost(object singletonInstance, params Uri[] baseAddresses)
        : base(singletonInstance, baseAddresses) { }

    protected override void OnOpening()
    {
        this.Description.Behaviors.Add(new IoCServiceHostBehavior());
        base.OnOpening();
    }
}

In my previous post, I used an example where I had a wcf service that used the Repository pattern with EntityFramework to query data instead of using the ObjectContext directly. I kept a parameterless constructor in the service and commented the constructor that should be used if I could have my service be resolved by the IoC container. Following the guidance of this post we can finally use that constructor and throw away the parameterless one.

[DbContextBehavior]
public class OrderService : IOrderService
{
    private readonly IOrderRepository orderRepository;
    //not used anymore
    //public OrderService()
    //{
    //    this.orderRepository = IoC.Current.Container.Resolve<IOrderRepository>();
    //}
    public OrderService(IOrderRepository repository)
    {
        this.orderRepository = repository;
    }
    //..
}

If we want to host our service in a console application we can simply do this:

var host = new IoCServiceHost(typeof(OrderService));
host.Open();
//wait for calls...
host.Close();

If we’re hosting it in an asp.net environment and have an .svc file we need to edit the asp markup file and specify a ServiceHostFactory class in the Factory attribute. The following code shows how we can write a ServiceHostFactory class uses our IoCServiceHost:

public class IoCServiceHostFactory : ServiceHostFactory
{
    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
    {
        return new IoCServiceHost(serviceType, baseAddresses);
    }
}

I’ve used this approach in several projects (professional and academic) and I’m very happy with the results. Being able to have my services be resolved with an IoC container helps me mantain/evolve my services in many different ways and always keep my code as clean and decoupled as possible. I hope you can take benefits from this technique too.

4 thoughts on “Resolving wcf service instances with an IoC container

  1. Hi,
    this is nice post. Can you share you work as a project what i mean source code. or can you send me the code with wcf project?

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