Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing unit of work in a WCF service with Autofac

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.

like image 207
Mehdi Khalili Avatar asked Apr 03 '12 06:04

Mehdi Khalili


1 Answers

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.

like image 134
Mehdi Khalili Avatar answered Oct 21 '22 23:10

Mehdi Khalili