How can I implement unit of work pattern in a WCF service with Autofac?
Injecting the same instance per call (or in Autofac terms LifetimeScope) of the unit of work interface into my services and repositories is easy using Autofac's wcf integration - what I am after is a way to commit the unit of work changes on return of WCF service call obviously ONLY if there has not been any exceptions.
I have seen Using a Custom Endpoint Behavior with WCF and Autofac which is basically how I started out but that does not deal with exceptions.
Currently what I have is an IOperationInvoker
that starts the unit of work in the Invoke and commits it only if there has not been any exceptions. The problem with this approach is that I need to resolve my unit of work instance inside the Invoke
method which gives me a different instance than the one injected into my services and repositories using AutofacInstanceProvider
.
Bradley Boveinis found a solution to this problem. We have not thoroughly tested it but it seems to work:
public class UnitOfWorkAwareOperationInvoker : IOperationInvoker
{
private readonly IOperationInvoker _baseInvoker;
public UnitOfWorkAwareOperationInvoker(IOperationInvoker baseInvoker)
{
_baseInvoker = baseInvoker;
}
public object[] AllocateInputs()
{
return _baseInvoker.AllocateInputs();
}
public object Invoke(object instance, object[] inputs, out object[] outputs)
{
var result = _baseInvoker.Invoke(instance, inputs, out outputs);
var context = OperationContext.Current.InstanceContext.Extensions.Find<AutofacInstanceContext>();
try
{
context.Resolve<IUnitOfWork>().Save();
}
catch (Exception ex)
{
var message = Message.CreateMessage(MessageVersion.Default, string.Empty);
new ElmahErrorHandler().ProvideFault(ex, null, ref message);
throw;
}
return result;
}
public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state)
{
return _baseInvoker.InvokeBegin(instance, inputs, callback, state);
}
public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result)
{
return _baseInvoker.InvokeEnd(instance, out outputs, result);
}
public bool IsSynchronous
{
get { return _baseInvoker.IsSynchronous; }
}
}
The key is in the following line:
OperationContext.Current.InstanceContext.Extensions.Find<AutofacInstanceContext>();
This grabs the UoW out of the ambient/current/contextual LifetimeScope.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With