2012-04-03 11 views
6

Come è possibile implementare l'unità di modello di lavoro in un servizio WCF con Autofac?Implementazione dell'unità di lavoro in un servizio WCF con Autofac

Iniettare la stessa istanza per chiamata (o in termini Autofac LifetimeScope) dell'unità di interfaccia di lavoro nei miei servizi e repository è facile utilizzando l'integrazione wcf di Autofac: quello che sto cercando è un modo per commettere l'unità di modifiche del lavoro su il ritorno del servizio di WCF chiama ovviamente SOLO se non ci sono state eccezioni.

Ho visto Using a Custom Endpoint Behavior with WCF and Autofac che è fondamentalmente come ho iniziato ma che non si occupa di eccezioni.

Attualmente quello che ho è un IOperationInvoker che avvia l'unità di lavoro in Invoke e lo impegna solo se non ci sono state eccezioni. Il problema con questo approccio è che ho bisogno di risolvere la mia istanza di unità di lavoro all'interno del metodo Invoke che mi dà un'istanza diversa da quella iniettata nei miei servizi e repository usando AutofacInstanceProvider.

+0

Supponiamo di aver registrato 'IUnitOfWork' nel contenitore. Come possiamo avvolgere una chiamata di servizio con essa e solo chiamare 'SaveChanges()' se non si sono verificate eccezioni? O dobbiamo prendere l'UoW nel costruttore di servizi? – jgauffin

+0

Quando si parla di chiamata di servizio, si intende la chiamata di servizio WCF? Se sì, il link che ho fornito sopra mostra come puoi farlo. L'unico problema è che devo ancora trovare un modo per salvare solo UoW se non c'è stata alcuna eccezione quando si utilizza AutoFac. –

+0

Hai detto tu stesso =) 'quello che sto cercando è un modo per commettere l'unità di cambio di lavoro al ritorno della chiamata di servizio WCF ovviamente SOLO se non ci sono state eccezioni. Questa è la parte difficile e quello che sto cercando. – jgauffin

risposta

1

Bradley Boveinis ha trovato una soluzione a questo problema. Non abbiamo accuratamente testato, ma sembra funzionare:

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 chiave è nella seguente riga:

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

Questa prende l'UoW fuori dalla ambient/corrente/LifetimeScope contestuale.

+1

Non esegue il commit delle modifiche anche se l'operazione genera un'eccezione? – jgauffin

+0

@jgauffin Non dovrebbe, come se ci fosse un'eccezione generata all'interno della chiamata di servizio, verrà lanciata alla chiamata _baseInvoker.Invoke (istanza, ingressi, uscite uscite) e tutto il codice sottostante che verrà ignorato. – xelibrion