Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
Erstellung von Instanzen mit geteilten Abhängigkeiten
t0ms3n
myCSharp.de - Member



Dabei seit:
Beiträge: 319

Themenstarter:

Erstellung von Instanzen mit geteilten Abhängigkeiten

beantworten | zitieren | melden

Hallo zusammen,

ich sitze gerade gedanklich vor dem Problem, wie die korrekte Injizierung von Abhängigkeiten aussieht, wenn diese Abhängigkeiten wiederum Abhängigkeiten teilen sollen. Das Stichwort hier ist sicherlich der Scope, aber dessen Verwendung ist mir nicht klar. Konkret geht es um die gemeinsame Nutzung einer Unit und somit auch die gemeinsame Verwendung von Transaktionen.

Als Beispiel könnten folgende Klassen dienen:


 class MyUnitOfWork
{
    public Guid Id { get; set; }

    public MyUnitOfWork()
    {
        Id = Guid.NewGuid();
    }
}

public class MyService1
{
    private readonly MyUnitOfWork _myUnitOfWork;

    public MyService1(MyUnitOfWork myUnitOfWork)
    {
        _myUnitOfWork = myUnitOfWork;
    }
}

public class MyService2
{
    private readonly MyUnitOfWork _myUnitOfWork;

    public MyService2(MyUnitOfWork myUnitOfWork)
    {
        _myUnitOfWork = myUnitOfWork;
    }
}

public class MyService3
{
    private readonly MyService1 _service1;
    private readonly MyService2 _service2;

    public MyService3(MyService1 service1, MyService2 service2)
    {
        _service1 = service1;
        _service2 = service2;
    }
}

Eine Verwendung ohne Container etc. könnte also so aussehen:


var instance1 = new MyService1(new MyUnitOfWork());
var instance2 = new MyService2(new MyUnitOfWork());

var sharedUnit = new MyUnitOfWork();
var instance3 = new MyService3(new MyService1(sharedUnit),  new MyService2(sharedUnit));

Allerdings muss hier der Aufrufende wissen, dass dies so sein muss, was letztlich auch nicht gewollt ist. Wie verbirgt MyService3 also, dass die beiden Abhängigkeiten eine geteilte Instanz von MyUnitOfWork haben sollen?

Edit: Titel von Verwendung von Scopes mit DI geändert. Denke dies ist ohne Bezug zu Container etc. erstmal treffender
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von t0ms3n am .
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 16109

beantworten | zitieren | melden

Ja, diesen Aufwand hat mal halt, wenn man keinen Container hat.
- performance is a feature -

Microsoft MVP - @Website - @blog - @AzureStuttgart - github.com/BenjaminAbt
private Nachricht | Beiträge des Benutzers
witte
myCSharp.de - Member



Dabei seit:
Beiträge: 966

beantworten | zitieren | melden

MyService3 müsste ein Uow injiziert bekommen und diesen an den beiden Subservices weiterreichen. Besser wäre Abts Vorschlag mit DIC und geeigneten Lifestyles der injizierten Objekte.
private Nachricht | Beiträge des Benutzers
t0ms3n
myCSharp.de - Member



Dabei seit:
Beiträge: 319

Themenstarter:

beantworten | zitieren | melden

Hmmm, also doch mit Container als Beispiel. (im Beispiel genutzt SimpleInjector)


var container = new Container();
// Es ginge zwar auch über eine Hybrid LifeTime, aber wie dann der Service3 zu injecten ist, konnte ich noch nicht raus finden. Dafür ist ja ein entsprechendes container.BeginExecutionContextScope() notwendig.
//container.Options.DefaultScopedLifestyle = new ExecutionContextScopeLifestyle();
//container.Register<MyUnitOfWork>(Lifestyle.CreateHybrid(() => container.GetCurrentExecutionContextScope() != null, Lifestyle.Scoped, Lifestyle.Transient));

container.Register<MyUnitOfWork>();
container.Register<MyService1>();
container.Register<MyService2>();
container.Register<MyService3>( () => MyService3Factory.CreateNew(container.GetInstance<MyUnitOfWork>()));

var instance1 = container.GetInstance<MyService1>();
var instance2 = container.GetInstance<MyService2>();
var instance3 = container.GetInstance<MyService3>();

Zusätzlich noch die Factory für MyService3.


public static class MyService3Factory
{
    public static MyService3 CreateNew(MyUnitOfWork unitOfWork)
    {
        return  new MyService3(new MyService1(unitOfWork), new MyService2(unitOfWork));
    }
}
private Nachricht | Beiträge des Benutzers
FZelle
myCSharp.de - Experte



Dabei seit:
Beiträge: 10083

beantworten | zitieren | melden

Wozu meinst du überhaupt die Factory zu brauchen?
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 16109

beantworten | zitieren | melden

Er will sicher gehen, dass der Aufrufer, der keinen Container nutzt, für beide Services (1 und 2) die identische UoW Instanz übergibt.

Ich stelle mal in den Raum, dass es ein Fehldesign darstellt, wenn eine Transaktion nur dann gültig ist, wenn _zwei_ Services diese füllen.
Das entspricht nicht ganz dem Sinn eines Service-Layers.
- performance is a feature -

Microsoft MVP - @Website - @blog - @AzureStuttgart - github.com/BenjaminAbt
private Nachricht | Beiträge des Benutzers
t0ms3n
myCSharp.de - Member



Dabei seit:
Beiträge: 319

Themenstarter:

beantworten | zitieren | melden

Das schließe ich nicht aus. Dann etwas mehr zur tatsächlichen Problemstellung die mich zu der Frage führte:

Ich habe in einer bestehender Implementierung einen Service ItemHistoryCollector. Dieser hat die Aufgabe Historieneinträge zu sammeln und zu speichern. Zusätzlich gibt es nun also einen weiteren Service welcher einen beliebigen Prozess abbildet z.B. Anlegen eines Auftrags. Im Rahmen dieser Prozesse sollen eben auch entsprechend Historieneinträge erzeugt werden, dazu würde der ItemHistoryCollector verwendet werden. Tatsächlich gespeichert werden sollen diese aber nur, wenn die Gesamtaktion erfolgreich war.

In der Theorie also: Beide nutzen die gleiche Datenbankverbindung, der Service zur Prozessabbildung beginnt eine Transaktion und Comitted diese eben acuh wieder.
private Nachricht | Beiträge des Benutzers
witte
myCSharp.de - Member



Dabei seit:
Beiträge: 966

beantworten | zitieren | melden

Könnte man auch so lösen dass der BL-Service wenn er erfolgreich seine Aufgabe erledigt hat (Autrag angelegt usw) ein History-Objekt daraus erzeugt und dieses in ein Eventsystem/Message Bus o.ä. an den History-Service übergibt und dieser das dann extra wegspeichert. Dann fällt diese extreme Kopplung der Services weg.
private Nachricht | Beiträge des Benutzers