Work in Progress
Diese Seite ist aktuell im Review! Die Seite wurde noch nicht qualitätsgesichert und kann Fehler enthalten.
Die verlinkten Seiten sind ggf. nur für Schleupen-Mitarbeiter sichtbar.

Muster: Anschluss Domäne an Service-Fassade

Dieses Dokument definiert, wie eine Service-Fassade implementiert und an die Programmlogik eines Domänenmodells delegiert wird.

Design

Die Service-Fassade nimmt die durch Kamoto) übergeben, der die eigentliche Logik schließlich implementiert.

Die Service-Fassade nimmt die durch Kamoto generierten Datenverträge entgegen und übersetzt diese mittels Assembler in Domänenobjekte. Diese werden an einen UseCase-Controller (siehe Usecase-Controller) übergeben, der die eigentliche Logik schließlich implementiert.

Die Service-Fassade wird als Webservice-Klasse gemäß in der Services-Assembly implementiert.

Implementierung

Die Klasse einer Service-Fassade muss so heißen wie die Schittstelle (ohne das I), damit die Dependency Injection via Castle funktioniert.

Die Anfragen werden an den Controller ManageBookCollectionController delegiert.

[ServiceBehavior(IncludeExceptionDetailInFaults = true, TransactionIsolationLevel = IsolationLevel.ReadCommitted)]
[ErrorHandlerBehavior(typeof(BuchServiceFaultAssembler), typeof(UnhandledFaultAssembler<UnhandledFaultContract>))]
public sealed class BuecherAusleihenActivityService : IBuecherAusleihenActivityService
{
   private IBuecherAusleihenController buecherAusleihenController;
   // ...

   public BuecherAusleihenActivityService(IBuecherAusleihenController buecherAusleihenController)
   {
      if (buecherAusleihenController == null) { throw new ArgumentNullException(nameof(buecherAusleihenController)); }
      
      this.controller = controller;
   }
   
   [OperationBehavior(TransactionScopeRequired = true)]
   public ExecuteResponse Execute(ExecuteRequest request)
   {
         if (request == null) { throw new ArgumentNullException(nameof(request)); }

         Guid[] buecher = request.Buecher.ToArray();
         Ausleihe ausleihe = buecherAusleihenController.LeiheAus(... buecher);
         AusleiheContract ausleiheContract = ausleiheAssembler.ToDataContract(ausleihe);

         return new ExecuteResponse(ausleiheContract);
   }
}

Dabei sollte die folgende Reihenfolge verwendet werden:

  1. Übersetzen von Datenvertrag in Domänenobjekt.
  2. Delegation der Aufgabe an den UseCase-Controller.
  3. Übersetzen von Domänenobjekt in Datenvertrag.

Fehlerbehandlung

Für Optimistic Locking existiert ein Schleupen.CS.PI.Framework.Services.ErrorHandling.StaleDataAssembler. Dieser wird zusätzlich zu dem bereits existierenden FaultAssembler angegeben.

Für das Optimistic Locking muss die Version-Eigenschaft von Datenvertrag zu Domänenobjekt und umgekehrt transportiert werden. Dieses darf nicht geändert werden.

Die Reihenfolge dabei ist so, dass der UnhandledFaultAssembler als letzter angegeben werden muss.

[ErrorHandlerBehavior(typeof(StaleDataAssembler<StaleDataFaultContract>), typeof(UnhandledFaultAssembler<UnhandledFaultContract>))]

Sofern der Typ der Id-Property im Domänenobjekt abweichend vom Default System.Guid gewählt wird - z.B. als ValueObject-Typ MyEntityId - muss er in der Variante des StaleDateAssembler mit zwei generischen Typ-Parametern als zweiter Parameter angegeben werden:

[ErrorHandlerBehavior(typeof(StaleDataAssembler<StaleDataFaultContract, MyEntityId>), typeof(UnhandledFaultAssembler<UnhandledFaultContract>))]

Der Typ MyEntityId muss hierzu die Schnittstellen IEntityIdData und IEquatable<MyEntityId> implementieren.

Cookie Consent mit Real Cookie Banner