1

Wir haben ein Singleton-Objekt erstellt (SsoSettingsProvider), in dem wir Objekt mit Lifestyle PerWebRequest (IReservationService in unserem Beispiel ist es WCF-Client) zu injizieren. Im Konstruktor verwenden wir dieses Objekt, um einige Daten zu erhalten, und wir platzieren diese Daten in einem privaten Feld.Schloss Windsor PerWebRequest Objekt in Singleton Objekt injiziert, ohne sie in Feld Referenzierung

public class SsoSettingsProvider : ISsoSettingsProvider 
    { 
     readonly LogonSettings _logonSettings; 


     public SsoSettingsProvider(IReservationService reservationService) 
     { 
      _logonSettings = reservationService.GetSSOSettings(); 
     }   
    } 

Wenn wir möglich Lebensstil Mismatches in Schloss Windsor suchen heißt es:

„Component 'SsoSettingsProvider/ISsoSettingsProvider' mit Lifestyle Singleton hängt von 'spät IReservationService gebunden' mit Lifestyle PerWebRequest Diese Art Abhängigkeit ist in der Regel nicht erwünscht und kann zu verschiedenen Arten von Fehlern führen. "

Diese Information sagt, dass es nur die Möglichkeit ist, aber in diesem Fall denke ich, es ist kein Problem, weil injizierten Objekt nicht in einem Feld verwiesen wird, so dass es Müll gesammelt werden kann. habe ich recht ?

+0

Bitte lesen Sie [diesen Artikel] (http://blog.ploeh.dk/2014/06/02/captive-dependency/), um das Problem zu verstehen. – Steven

+0

danke für den Artikel. Ich bin mir dieses Verhaltens bewusst, aber es ist nicht das gleiche Szenario. Wenn ich den Artikel auf meine Situation abbilde, sollten wir auf 'IRservationService' in einem Feld von' SsoSettingsProvider' verweisen. In meinem Beispiel wird es einmal verwendet. – RedgoodBreaker

+1

Und [dieser Artikel] (http://blog.ploeh.dk/2011/03/03/InjectionConstructorshouldbesimple/) trifft auch auf Ihre Situation zu. – Steven

Antwort

1

In diesem Fall denke ich, es ist kein Problem, da das injizierte Objekt nicht in einem Feld referenziert wird, so dass es Garbage Collected sein kann. habe ich recht?

Castle Windsor warnt vor Captive Dependencies. Das Hauptproblem besteht nicht so sehr darin, dass Instanzen keine Speicherbereinigung sind, sondern eine Klasse eine Instanz wiederverwenden wird, die nicht wiederverwendet werden soll.

Ein einfaches Beispiel ist, wenn Sie eine DbContext in eine Klasse injizieren, die als Singleton konfiguriert ist. Dies führt jedoch dazu, dass DbContext am Leben gehalten wird, bis sein Singleton-Verbraucher seinen Geltungsbereich verlässt (was normalerweise der Fall ist, wenn die Anwendung endet). A DbContext sollte jedoch nicht über mehrere Anfragen wiederverwendet werden. Zum einen, weil es einfach nicht threadsicher ist. Darüber hinaus wird es sehr bald veraltet, wodurch es zwischengespeicherte Daten zurückgibt, anstatt die Datenbank erneut abzufragen.

Aus diesem Grund wir register DbContext typically as Scoped. Dies bedeutet jedoch, dass alle seine Kunden höchstens so lange wie die DbContext leben sollten, um zu verhindern, dass die Anwendung bricht. Darüber warnt Castle.

In Ihrem Fall jedoch speichern Sie nicht die IReservationService in einem privaten Feld von SsoSettingsProvider. Dies wäre immer noch ein Problem, da es vernünftig wäre zu erwarten, dass die Objekte, die IReservationService zurückgeben, die IReservationService nicht überdauern (andernfalls würde IReservationService als Singleton registriert werden). Da aus der Sicht der SsoSettingsProvider, es gibt keine Möglichkeit zu wissen, ob es sicher ist, LogonSettings zu speichern, ist es viel besser, überhaupt nicht zu speichern.

Darüber hinaus, wie here ausgedrückt, sollten Injektion Konstruktoren ihre Abhängigkeiten überhaupt nicht verwenden. Dies führt zu einer langsamen und unzuverlässigen Objektzusammensetzung.

Also auch wenn Sie Ihr Design analysiert haben könnte und weiß sicher, dass dies in Ihrem Fall funktioniert, würde ich Ihnen eine der folgenden Dinge vorschlagen tun:

  • Shop IReservationService als privates Feld in SsoSettingsProvider und Rufen Sie GetSSOSettings nur auf, wenn einer der SsoSettingsProvider Mitglieder aufgerufen wird und verhindern Sie die Speicherung LogonSettings. Dies zwingt Sie dazu, entweder SsoSettingsProvider scoped oder IReservationService singleton zu machen. Ob IReservationService Singleton sein kann oder nicht, kann man nur herausfinden.
  • Bei SsoSettingsProvider interessiert sich nur für LogonSettings und LogonSettings ist ein konstanter Wert, der sich nicht ändern, nachdem die Anwendung gestartet wird, sollten Sie LogonSettings direkt in SsoSettingsProvider ‚s Konstruktor injizieren. Dies vereinfacht SsoSettingsProvider und verschiebt das Laden des LogonSettings auf den Composition Root.
+0

in meinem Fall habe ich konstanten Wert. Also ich denke, die beste Option ist usung '.UsingFactoryMethod()' – RedgoodBreaker

+0

Wenn es ein Wert ist, der sich nicht ändert, nachdem die Anwendung gestartet wurde, registrieren Sie es als Singleton-Instanz mit '.Instance'. Das wäre viel einfacher als die Verwendung von '.UsingFactoryMethod'. – Steven

+0

, aber ich muss 'SsoSettingsProvider' WCF Client aufrufen, um' LogonSettings' vom Remote-Service zu erhalten. Also muss ich die Instanz o 'SsoSettingsProvider' – RedgoodBreaker

Verwandte Themen