2012-04-03 12 views
6

Wie kann ich Arbeitseinheitsmuster in einem WCF-Dienst mit Autofac implementieren?Implementieren der Arbeitseinheit in einem WCF-Dienst mit Autofac

Das Einfügen der gleichen Instanz pro Aufruf (oder in Autofac Terms LifetimeScope) der Einheit der Arbeit Schnittstelle in meine Dienste und Repositories ist einfach mit Autofacs wcf-Integration - was ich möchte, ist eine Möglichkeit, die Änderung der Arbeitseinheit zu verpflichten Rückgabe des WCF-Serviceanrufs NUR, wenn es keine Ausnahmen gab.

Ich habe Using a Custom Endpoint Behavior with WCF and Autofac gesehen, das ist im Grunde, wie ich begann, aber das behandelt Ausnahmen nicht.

Derzeit habe ich eine IOperationInvoker, die die Arbeitseinheit in der Invoke startet und nur dann festlegt, wenn es keine Ausnahmen gab. Das Problem bei diesem Ansatz besteht darin, dass ich meine Arbeitseinheitsinstanz innerhalb der Invoke-Methode auflösen muss, die mir eine andere Instanz als die in meine Dienste und Repositorys unter Verwendung von AutofacInstanceProvider injizierte Instanz gibt.

+0

Nehmen wir an, wir haben ein 'IUnitOfWork' im Container registriert. Wie können wir einen Service-Aufruf damit umbrechen und 'SaveChanges()' nur aufrufen, wenn keine Ausnahme aufgetreten ist? Oder müssen wir die UoW im Service-Konstruktor nehmen? – jgauffin

+0

Wenn Sie Serviceanruf sagen, meinen Sie WCF-Serviceanruf? Wenn ja, dann zeigt der oben angegebene Link, wie Sie das tun können. Das einzige Problem ist, ich muss noch einen Weg finden, nur die UoW zu speichern, wenn es keine Ausnahme bei der Verwendung von AutoFac gab. –

+0

Sie sagten es selbst =) 'was ich danach bin, ist ein Weg, um die Einheit der Arbeit Änderungen bei der Rückkehr von WCF Service Anruf offensichtlich nur dann, wenn es keine Ausnahmen gab. Das ist der schwierige Teil und was ich suche. – jgauffin

Antwort

1

Bradley Boveinis hat eine Lösung für dieses Problem gefunden. Wir haben nicht getestet es gründlich, aber es scheint zu funktionieren:

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

Der Schlüssel in der folgenden Zeile ist:

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

Dieser packt die UOW aus dem Umgebungs/Strom/kontextueller LifetimeScope.

+1

Werden die Änderungen nicht übernommen, auch wenn die Operation eine Ausnahme auslöst? – jgauffin

+0

@jgauffin Es sollte nicht, als ob eine Ausnahme in Serviceaufruf geworfen wird, es wird auf _baseInvoker.Invoke (Instanz, Eingänge, Ausgänge) Aufruf und der gesamte Code darunter wird ignoriert werden. – xelibrion