2016-10-28 2 views
5

Ich benutze eine Castle Windsor typisierte Fabrik. In unserem Registrierungscode wird es so einrichten, kann es eine transiente Komponente erstellen:Castle Windsor typisierte Fabrik ohne Freigabe leckt nicht

container.AddFacility<TypedFactoryFacility>(); 
container.Register(Component.For<IThingFactory>().AsFactory()); 
container.Register(Component.For<IThing>().ImplementedBy<TransientObject>().Named("TransientObject").LifeStyle.Transient); 

Von meinem Verständnis von the Castle Windsor Typed Factory documentation dachte ich, dass ein Transient Objekt muss von einem typisierten Fabrik Verfahren gelöst werden, da sonst die typisierten Fabrik würde Behalte einen Verweis auf das Objekt. Ich habe versucht, dies zu beweisen, indem ich einen Test schreibe, der die in this StackOverflow article erläuterte Methode verwendet.

Aber zu meiner Überraschung scheitert es eigentlich nicht, was bedeutet, dass, obwohl ich das transiente Objekt nicht zur Fabrik freigegeben habe, es immer noch vom GC zurückgewonnen werden kann. Ich bin besorgt, dass mein Test vielleicht irreführend ist und es wirklich ein Leck gibt.

Also meine Frage ist: ist mein Test falsch, oder ist die Dokumentation falsch?

Hier ist der Test:

var factory = container.Resolve<IThingFactory>(); 
WeakReference reference = null; 
new Action(() => 
     { 
      var service = factory.GetTransientObject(); 
      reference = new WeakReference(service, true); 
     })(); 

GC.Collect(); 
GC.WaitForPendingFinalizers(); 
Assert.That(reference.Target, Is.Null, "reference should be null"); 
+0

was ist die Frage? –

+0

Erweitert/implementiert Ihre "IThing" IDisposable Schnittstelle? Es steht geschrieben, dass "Windsor immer Einweg-Nicht-Singleton-Komponenten verfolgt, die über eine typisierte Fabrik aufgelöst werden." – piotrwest

+0

Ich glaube, piotrwest hat meine Frage beantwortet: Nein, mein IThing implementiert IDisposable nicht. Ich hatte die Implikationen von "Windsor immer Tracks _ disposable _..." vermisst. Vielen Dank! – MrBlueSky

Antwort

4

Windsor verfolgt Transient Fällen nur, wenn sie einige decommission Bedenken haben. Ein typisches Beispiel für ein Problem mit der Außerbetriebnahme ist, dass eine Klasse die Schnittstelle IDisposable implementiert. So

, wenn die IThingTransient ist und es nicht implementiert IDisposableund es hat keine andere decommission betrifft dann Windsor wird es NICHT und Garbage Collector verfolgen können/werden Instanzen von IThing entfernen.

ABER (und das ist ein großes aber), ich schlage vor, Sie verlassen sich nie auf dieses Verhalten. IThing kann von einem Entwickler geändert werden, und es kann zukünftig entsorgt werden. Oder es könnte ein weiteres Problem mit der Außerbetriebnahme auftreten. Und plötzlich tritt ein Speicherleck auf. Daher sollte eine einfache Regel befolgt werden:

Jedes Mal, wenn ein Objekt durch Aufruf von container.Resolve explizit aufgelöst wird, muss es durch Aufruf von container.Release freigegeben werden. Auch wenn ein Objekt explizit von einer getippten Factory erstellt wird, muss es explizit durch die typisierte Factory zerstört werden. Egal, ob das Objekt vorübergehend ist oder nicht, achten Sie auf seine Lebensdauer. Immer. Der Schöpfer eines Objekts (sei es Windsor oder getippte Fabrik) ist verantwortlich für die Zerstörung des Objekts.

Im Grunde war @piotrwest in seinem Kommentar richtig. Diese Antwort soll jedoch erklären, dass es nicht nur um IDisposable geht - es geht um Dekommissionsbelange (IDisposable ist einfach einer von ihnen).

This great article erklärt weitere Details.

+0

Großartige Erklärung! – AsValeO

Verwandte Themen