WCF and Unity 2.0

30 בנובמבר 2010

4 comments

In my previous posts on Unity 2.0 and infrastructure and Unity 2.0 and application architecture I've shown how can Unity 2.0 can be used In order to create loose coupled layers in your application and I've explained how dependency injection can be used for this matter.

If you are developing a distributed application using WCF services (very common scenario this days…) you might consider using Unity 2.0 With WCF services and therefore use dependency injection pattern throughout your application.

Think about a scenario when you got an client application developed against your WCF services but you haven't got to develop the services yet.

In this scenario you have to provide the service contract for your services and the developers of the client application can create their own application Using their own implementation using mock services (check out my previous posts to see how it's done).

Let's get to work.

Extending WCF to work with Unity 2.0

in order to work with Unity 2.0 containers in WCF, you'll need to extend some components.

Creating a custom instance provider

The IInstanceProvicder interface is responsible for the creating and the recycling of the service. The following code implement this interface using a Unity container.

namespace Common.WCF
{
public class UnityInstanceProvider : IInstanceProvider
{
public UnityContainer Container { set; get; }
public Type ServiceType { set; get; }


public UnityInstanceProvider() : this(null)
{
}

public UnityInstanceProvider(Type type)
{
ServiceType = type;
Container = new UnityContainer();
}

// Get Service instace via unity container
public object GetInstance(InstanceContext instanceContext, Message message)
{
return Container.Resolve(ServiceType);
}

public object GetInstance(System.ServiceModel.InstanceContext instanceContext)
{
return GetInstance(instanceContext, null);
}

public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
}
}
}

Create a custom service behavior

We'll create the custom service behavior to use our custom instance provider at run time. When ApplyDispatchBehaviour event is evoked, each end point will get the instance provider.

namespace Common.WCF
{
public class UnityServiceBehavior : IServiceBehavior
{
public UnityInstanceProvider InstanceProvider { get; set; }
private ServiceHost serviceHost = null;

public UnityServiceBehavior()
{
InstanceProvider = new UnityInstanceProvider();
}

public UnityServiceBehavior(UnityContainer unity)
{
InstanceProvider = new UnityInstanceProvider();
InstanceProvider.Container = unity;
}

public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase,
        Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{

}

public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (ChannelDispatcherBase cdb in serviceHostBase.ChannelDispatchers)
{
ChannelDispatcher cd = cdb as ChannelDispatcher;
if (cd != null)
{
foreach (EndpointDispatcher ed in cd.Endpoints)
{
InstanceProvider.ServiceType = serviceDescription.ServiceType;
ed.DispatchRuntime.InstanceProvider = InstanceProvider;
}
}
}
}

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

Creating a custom service host

The service host is responsible for loading the service and applying all configuration data for it. Here we'll create a Unity container for the service behavior to use.

namespace Common.WCF
{
public class UnityServiceHost : ServiceHost
{
public UnityContainer Container { get; set; }


public UnityServiceHost()
: base()
{
Container = new UnityContainer();
}

public UnityServiceHost(Type serviceType, params Uri[] baseAddresses) : base(serviceType,baseAddresses)
{
Container = new UnityContainer();
}

protected override void OnOpening()
{
base.OnOpening();

if (this.Description.Behaviors.Find<UnityServiceBehavior>() == null)
this.Description.Behaviors.Add(new UnityServiceBehavior(Container));

}
}
}

Creating a custom service host factory

The service host factory class will help us create our custom service host dynamically at run time. Here the container will read it's data from the configuration.

namespace Common.WCF
{
public class UnityServiceHostFactory : ServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
UnityServiceHost serviceHost = new UnityServiceHost(serviceType, baseAddresses);
UnityContainer container = new UnityContainer();
serviceHost.Container = container;

//configure container
UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
section.Configure(serviceHost.Container);
return serviceHost;
}
}
}

Creating a unity WCF Service

All use need to do now is add a reference to the service host factory. Here's an SVC file for example :

<%@ ServiceHost Language="C#" Debug="true" Service="Server.Services.ExampleService"
Factory="Common.WCF.UnityServiceHostFactory" %>

That's it. Just configure the service contract in the Unity configuration section on your web.config file and you're set to go.

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

4 comments

  1. Colin Skopinski7 בדצמבר 2010 ב 19:55

    Great post! I had two quick questions. First, is there any harm in removing serviceHost member in the UnityServiceBehavior class? It doesn't appear to be used. Also, how would you leverage the UnityHost if you were hosting your service as a Windows service as opposed to a web service? Thanks!

    Reply
  2. Rui Jarimba1 בדצמבר 2011 ב 19:08

    Hi Gadi,

    Thank you for your post, it was really helpful.

    My services resources weren't being disposed using this classes. In order to do that, I've changed ReleaseInstance method in UnityInstanceProvider class:

    public void ReleaseInstance(InstanceContext instanceContext, object instance)
    {
    var myInstance = instance as IDisposable;

    if(myInstance != null)
    myInstance.Dispose();
    }

    Best regards,
    Rui Jarimba

    Reply
  3. Cleyton3 במאי 2012 ב 12:19

    Hi,

    Can you show us hot to configure the service contract in the Unity configuration section on my web.config file?

    I am not sure how to do this.

    Cheers

    C

    Reply
  4. Jairo3 במאי 2012 ב 20:00

    Great article.
    Please Gadi, as Cleyton asked, provide a sample config file for the sake of completeness.
    Thanks again.

    Reply