I’ve needed to use autofac recently inside WCF 4 services. Services are hosted using Windows Server AppFabric. This post is about it
Some time ago I’ve started new open-source project OnAgile. This is Agile project and task management tool that uses cutting-edge technologies ( WCF 4, Silverlight 4, NHibernate 3, Postgre SQL 9x). But thats another long and interesting story.
Once I had created basic proto for my WCF services and Silverlight client I faced with the need of IoC for my services. My first attempt was to use autofac IoC. Let’s assume we’ve got following service contract and implementation:
[ServiceContract]
public interface IService1
{
[OperationContract]
int Foo();
}
public class Service1 : IService1
{
public Service1(ICalculator calculator)
{
this.calculator = calculator;
}
#region IService1 Members
public int Foo()
{
return calculator.Calculate();
}
#endregion
private ICalculator calculator;
}
As you can see our service depends on ICalculator interface. Here it is (with implementation):
public interface ICalculator
{
int Calculate();
}
public class ConstCalculator : ICalculator
{
#region ICalculator Members
public int Calculate()
{
return 5;
}
#endregion
}
Our goal is to inject ICalculator inside constructor of IService1 concrete implementation (e.g. Service1). First of all let’s create custom IInstanceProvider implementation:
public class IocInstanceProvider : IInstanceProvider
{
public IocInstanceProvider(Type serviceType, IContainer container)
{
this.serviceType = serviceType;
this.container = container;
}
#region IInstanceProvider Members
public object GetInstance(InstanceContext instanceContext, Message message)
{
return ResolveUnregistered(serviceType, container); // container.Resolve(serviceType);
}
public object GetInstance(InstanceContext instanceContext)
{
return GetInstance(instanceContext, null);
}
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
if (instance is IDisposable)
{
((IDisposable)instance).Dispose();
}
}
public object ResolveUnregistered(Type type, IContainer container)
{
var constructors = type.GetConstructors();
foreach (var constructor in constructors)
{
try
{
var parameters = constructor.GetParameters();
var parameterInstances = new List<object>();
foreach (var parameter in parameters)
{
var service = container.Resolve(parameter.ParameterType);
if (service == null) throw new Exception();
parameterInstances.Add(service);
}
return Activator.CreateInstance(type, parameterInstances.ToArray());
}
catch { }
}
throw new Exception();
}
#endregion
private readonly Type serviceType;
private readonly IContainer container;
}
Key methods are GetInstance() and ResolveUnregistered(). First one is called when WCF runtime actually needs to create new instance of service. Second one allows to overcome autofac limitations — autofac can’t resolve unregistered types. I’ll cover why this is important later.
Now let’s create custom service behavior that will allow us to use our IocInstanceProvider:
public class IoCServiceBehavior : Attribute, IServiceBehavior
{
public IoCServiceBehavior()
{
builder = new ContainerBuilder();
builder.RegisterType<ConstCalculator>().As<ICalculator>();
}
#region IServiceBehavior Members
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase,
Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{
}
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, builder.Build());
}
}
}
}
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
}
#endregion
private readonly ContainerBuilder builder;
}
Inside constructor of IoCServiceBehavior we do create autofac containerBuilder and register needed types. As you know we can apply our behavior to any service by subclassing from Attribute. That is why it is really important not to register our actual services inside container builder and that is why ResolveUnregistered() method was previously introduced. I’m really missing Unity and it’s kindness of resolving of unregistered types. Anyways… lets mark our service with IoCServiceBehavior attribute:
[IoCServiceBehavior]
public class Service1 : IService1
{
public Service1(ICalculator calculator)
{
this.calculator = calculator;
}
#region IService1 Members
public int Foo()
{
return calculator.Calculate();
}
#endregion
private ICalculator calculator;
}
And we’re done:
You can download sources here (zip archive, 8.88 Kb)


