Improve WCF services testability with simple Dependency Injection
Dependency injection is a great technique to reduce coupling between components and improve testability. There are few techniques we can create dependency injections, you can use a framework like MEF or spring to Automate dependency injection but I personally favor manually injected dependencies. call me old fashion, but I like creating object via simple constructor calls (most of the time).
This is really straight forward most of the time but when dealing with WCF services there is a slight complexity to take in to consideration. In most scenarios WCF is in charge of instantiating the service class (the only exception here is with single instance context mode, where we can supply ServiceHost with a ready made instance of our service class).
Lately I have come across a really cool (and simple) option in WCF Web API. The WCF Web API supply an HttpConfiguration API that exposes a CreateInstance delegate we can use to manually create a new instance of our service class:
config.CreateInstance = (type, context, message) =>
{
IPlayersDal dal = new PlayersDal();
return new PlayersCURD(dal);
};
var factory = new HttpServiceHostFactory() { Configuration = config };
While this API is cool, it can only be used for http based services (using the WCF Web API). I really felt like using something like that in a SOAP based project I am currently working on so I figured what the hack, I can create the similar solution (source code can be found here) for any WCF service host out there.
The first stop was creating an IExtension<ServiceHostBase> that can transport the delegate down the WCF pipeline:
{
public Func<object> InstanceInitializer;
public void Attach(ServiceHostBase owner)
{
}
public void Detach(ServiceHostBase owner)
{
}
}
Next we need to create an instance provider. this is the runtime component that WCF actually uses to create a new instance of the service class:
{
public object GetInstance(InstanceContext instanceContext, Message message)
{
var extension = instanceContext.Host.Extensions.Find<InstanceInitializerExtension>();
return extension.InstanceInitializer();
}
public object GetInstance(System.ServiceModel.InstanceContext instanceContext)
{
return GetInstance(instanceContext, null);
}
public void ReleaseInstance(System.ServiceModel.InstanceContext instanceContext, object instance)
{
}
}
To hook the the ManualInstanceProvider we need to create a service behavior and implement the ApplyDispatchBehavior method like this:
{
foreach (ChannelDispatcherBase cdb in serviceHostBase.ChannelDispatchers)
{
ChannelDispatcher cd = cdb as ChannelDispatcher;
if (cd != null)
{
foreach (EndpointDispatcher ed in cd.Endpoints)
{
ed.DispatchRuntime.InstanceProvider = new ManualInstanceProvider();
}
}
}
}
The last thing we need to do is create an extension method for ServiceHostBase that will allow setting the delegate as the factory function of our host:
{
// adding a behavior that hocks up the ManualInstanceProvider
host.Description.Behaviors.Add(new InstanceCreationBehavior());
// passing the instance initialize down the rabbit hole
host.Extensions.Add(new InstanceInitializerExtension
{ InstanceInitializer = instanceInitializer });
}
Now we are ready to create our service host:
host.ConfigureInstanceFactory(() => new PlayersService(new PlayersDal()));
host.Open();
Summary
Using dependency injection can some (if not most) of the time a simple task. Using this extension we can utilize whichever technique we choose.
Yaniv




