Ich habe das folgende Codebeispiel:
%Vor% Jetzt - ist das wirklich schlimm? Ich bin mir nicht sicher, aber das scheint ziemlich dasselbe zu sein wie nicht den Destruktor der Basisklasse virtuell in C++
.
Ich möchte nicht, dass die IRepository
-Schnittstelle IDisposable
implementiert, weil das zu unerwünschter Komplexität und einer Menge von Klassen führen würde, die auch IDisposable
implementieren müssten.
Wie soll dieser Fall behandelt werden?
Ich bin mir sicher, dass dies in jeder Typhierarchie vorkommen kann - wenn einer der abgeleiteten Typen verfügbare Ressourcen verwalten muss.
Also, was soll ich tun - ziehen Sie IDisposable
bis zur allerersten Schnittstelle hoch oder lassen Sie es so, und ich hoffe, der Benutzer würde Einweg- und Nicht-Wegwerf-Repositories unterscheiden.
Danke.
Was Sie beschrieben haben, ist mit einem wichtigen Vorbehalt in Ordnung: Ein Objekt eines Typs, der seiner Basis "IDisposable" hinzugefügt hat, darf niemals an einen Verbraucher weitergegeben werden, der das Objekt für eine unbekannte Dauer halten oder persistieren könnte.
Grundsätzlich muss der Eigentümer eines IDisposable-Objekts (*) entweder dafür sorgen, dass das Objekt selbst entsorgt wird, oder das Objekt an einen neuen Eigentümer übergeben, der die Verantwortung übernehmen und respektieren kann. Anfänglich sind IDisposable-Objekte im Allgemeinen ihrem Ersteller "gehört", aber Handoffs sind üblich. Ein Verweis auf ein IDisportierbares Objekt kann einem anderen Objekt übergeben werden, ohne das Eigentum zu übertragen; In diesem Szenario ist der Besitzer immer noch dafür verantwortlich, das Objekt zu entsorgen, wenn es nicht mehr benötigt wird. Dazu muss der Besitzer wissen, dass das Objekt nicht mehr benötigt wird. Die häufigsten Muster sind:
Wenn eines dieser Muster zutrifft, können Sie in guter Verfassung sein. Wenn nicht, könntest du in Schwierigkeiten sein.
Ja, ich würde sagen, das ist schlecht - weil Sie nicht alle Repositories auf die gleiche Weise verwenden können.
Ich würde persönlich die Repository-Schnittstelle erweitern IDisposable
- es ist einfach genug, um es schließlich mit einem No-Op implementieren.
Dies ist genau die selbe Wahl, wie sie von Stream
, TextReader
und TextWriter
im Hauptrahmen gemacht wird. StringWriter
(zum Beispiel) muss nichts loswerden ... aber TextWriter
ist immer noch verfügbar.
Das kommt daher, weil IDisposable
in gewisser Weise eine seltsame Schnittstelle ist: Es vermittelt nicht etwas, das den Anrufern angeboten wird ... es vermittelt etwas, das erforderlich ist von Anrufern (oder zumindest, stark ermutigt mit möglichen Problemen, wenn Sie nicht mitmachen).
Das einzige Problem, das Sie möglicherweise haben, ist, wenn Sie eine Art von Factory, Inversion of Control oder Dependency Injection pattern / framework verwenden. Wenn Sie das Objekt als Schnittstelle verwenden möchten, können Sie dies nie tun:
%Vor%Sie möchten vielleicht ein INHibernateRepository vorstellen, das IDisposable implementiert. Da IDisposable normalerweise eine solche Operation auf niedriger Ebene ist, gibt es kein großes Problem damit, dass Ihre Schnittstellen diese Schnittstelle implementieren.
Nein, ziehe das IDisposable nicht hoch. Halten Sie die Schnittstellen atomar, einfach und unabhängig.
Wenn Sie nicht argumentieren können, dass IDisposable ein fundamentales Merkmal des IRepository ist (und SampleRepository zeigt, dass dies nicht der Fall ist), sollte es keine Ableitung zwischen den beiden geben.
Das scheint mir vollkommen in Ordnung zu sein. Was ist das Problem?
Erstens, um Ihre Frage zu beantworten. Das Dispo-Muster unterscheidet sich von einem C ++ - Destruktor. Eine Dispose
-Methode soll die Ressourcen der Klasse beseitigen, anstatt die -Klasse selbst zu entfernen .
Der Grund für das Markieren von C ++ - Destruktoren als virtual
ist in .NET nicht vorhanden, da jede Instanz eines Referenztyps einen Sync-Block enthält, der Informationen zum Laufzeittyp enthält. Auf diese Weise kann der Garbage Collector die korrekte Speichermenge entsprechend wiederherstellen.
Wie man IRepository
mit IDisposable
erweitert, wäre das eine schnelle Lösung, die in den allermeisten Fällen akzeptabel wäre. Der einzige Einwand, den ich sehen kann, ist, dass die Erweiterung der Schnittstelle alle abgeleiteten Klassen erfordert, um die Schnittstelle zu implementieren. Auf den ersten Blick scheint es einfach zu sein, eine Schnittstelle mit NOPs zu implementieren (vielleicht mehrere Male), aber das sollte nicht sein müssen. Aber ich kann eine Alternative anbieten.
Verwenden Sie stattdessen eine abstrakte Basisklasse, die das Dispose-Muster implementiert. Dies würde der Struktur der "Standard" -Implementierung des Verfügungsmusters folgen.
%Vor%Werfen Sie einen Blick auf die Anleitung zum Löschen von Mustern , die von Microsoft geschrieben wurden, um ein detaillierteres Beispiel zu sehen .
Tags und Links c# interface disposable