2012-04-03 15 views
6

¿Cómo puedo implementar el patrón de unidad de trabajo en un servicio WCF con Autofac?Implementación de la unidad de trabajo en un servicio WCF con Autofac

Inyectar la misma instancia por llamada (o en Autofac terms LifetimeScope) de la interfaz de la unidad de trabajo en mis servicios y repositorios es fácil usando la integración wcf de Autofac. Lo que busco es una forma de confirmar los cambios en la unidad de trabajo la devolución de la llamada de servicio WCF obviamente SÓLO si no ha habido ninguna excepción.

He visto Using a Custom Endpoint Behavior with WCF and Autofac que es básicamente como empecé, pero eso no se ocupa de las excepciones.

Actualmente, lo que tengo es un IOperationInvoker que inicia la unidad de trabajo en la Invocación y la confirma solo si no ha habido ninguna excepción. El problema con este enfoque es que necesito resolver mi instancia de unidad de trabajo dentro del método Invoke que me da una instancia diferente a la que se inyectó en mis servicios y repositorios usando AutofacInstanceProvider.

+0

Supongamos que hemos registrado un 'IUnitOfWork' en el contenedor. ¿Cómo podemos envolver una llamada de servicio con ella y solo llamar a 'SaveChanges()' si no se ha producido ninguna excepción? ¿O tenemos que tomar la UoW en el constructor del servicio? – jgauffin

+0

Cuando dice una llamada de servicio, ¿se refiere a la llamada de servicio WCF? Si es así, entonces el enlace que he proporcionado arriba muestra cómo puede hacerlo. El único problema es que aún tengo que encontrar una manera de guardar solo la UoW si no ha habido ninguna excepción al usar AutoFac. –

+0

Lo dijo usted mismo =) 'lo que busco es una forma de confirmar los cambios en la unidad de trabajo a la vuelta de la llamada de servicio WCF, obviamente, SÓLO si no ha habido ninguna excepción. Esa es la parte difícil y lo que estoy buscando. – jgauffin

Respuesta

1

Bradley Boveinis encontró una solución a este problema. No hemos probado a fondo, pero parece que funciona:

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; } 
    } 
} 

La clave está en la línea siguiente:

OperationContext.Current.InstanceContext.Extensions.Find<AutofacInstanceContext>(); 

Este agarra el UoW fuera del ambiente/corriente/LifetimeScope contextual.

+1

¿No confirma los cambios incluso si la operación arroja una excepción? – jgauffin

+0

@jgauffin No debería, como si hubiera una excepción lanzada dentro de una llamada de servicio, que se lanzará en la llamada _baseInvoker.Invoke (instancia, entradas, salidas de salida) y todos los códigos que se muestran a continuación serán ignorados. – xelibrion

Cuestiones relacionadas