Ich verwende MEF, um die Schnittstelle zur Implementierungsklasse als eine Art von DI zuzuordnen. Zum Beispiel verwende ich das Import-Attribut für eine Schnittstelle und den Export für die Implementierungsklasse. Nach meinem Verständnis wird das MEF-Framework die Instanzen der Implementierungsklasse erstellen und sie im MEF-Container zur Verwendung oder automatischen Injektion speichern.Komponenten über MEF-Container entsorgen?
Einige meiner Implementierungsklassen implementieren die IDispose-Schnittstelle. Da Instanzen von MEF erstellt werden, sollte ich das MEF veranlassen, die Dispose-Methode der Komponenten aufzurufen, wenn sie verfügbar sind, wenn die MEF nicht verfügbar ist. In meiner Anwendung habe ich beispielsweise einen Verweis auf den Container des MEF. Wenn die Anwendung beendet wird, rufe ich die Dispose-Methode des Containers auf. Das Problem ist, dass die Dispose meiner Komponenten nie aufgerufen wird.
Hier sind einige Beispiel-Codes über den Import und Export-Mapping:
[Import]
private IMyInterface IComponent1 { get; set; }
....
[Export]
private IMyInterface Component {
get {
var instance = new MyImplemetation();
....
return instance;
}
}
....
Es gibt viele andere Import- und Exportdefinitionen für andere Zuordnungen in ähnlicher Weise. Auf diese Weise konstruiere ich Zuordnungen, so dass das MEF die Beziehungen und die Art und Weise, wie die zugeordneten Instanzen erstellt werden, kennt. Hier sind einige Codes in meiner Anwendung Zuordnungen zu laden, indem Sie Assembly mit:
var catalog = new AggregateCatalog();
catalog.Add (new AssemblyCatalog(Assembly.GetExecutingAssembly());
var batch = new CompositionBatch();
batch.AddPart(catalog);
// MEF container has all the mappings
var container = new CompositionContainer(catalog);
....
// Get instance from container
var instance = container.GetExportedValue<IMyInterface>();
// my instance CTOR has a contructor with several other
// implementation instances injected by interface
// instance starts to do its job and coordinates others ...
instance.Start();
....
// Finally the job is done.
// Dispose the container explicitly there.
container.Dispose();
// But my components are never disposed
// this results some connections not being closed
// file streams not being closed...
hier die Instanz viele andere Komponenten durch CTOR durch den MEF injiziert hat. Diese Komponenten enthalten auch andere Komponenten, die von der MEF injiziert werden. Das Problem ist, dass es wirklich schwer ist, Entscheidungen zu treffen, wenn Komponenten entsorgt werden sollen, da einige Instanzen geteilt werden. Wenn ich bei einem Dispose anrufe, würde das dazu führen, dass andere es nicht benutzen können. Wie Sie in diesem Bild sehen können, werden Instanzen von der MEF erstellt und in meine Anwendungsklassen injiziert. Jede Komponente sollte keine Kenntnis von anderen haben, und sie sollte injizierte Komponenten verwenden, um die Aufgabe zu erfüllen.
Ich bin mir nicht sicher, wo/wie ich das MEF anweisen sollte, Dispose für Komponenten aufzurufen, wenn die Anwendung beendet oder der Container entsorgt wird? Soll ich die Dispose auf Komponenten aufrufen? Ich denke nicht, dass das richtig ist, da die MEF sie erstellt und sie bei Bedarf in die Kunden injiziert. Die Clients sollten ihre Dispose nicht aufrufen, wenn sie ihre Arbeit beendet haben.
Ich denke, dass Daniel es schön erklärt hat. Ich habe die Instanz in meinem Export-Eigenschaft-Getter erstellt. Es macht Sinn, die Instanz zu halten und von dort zu reinigen. Ich bevorzuge es, den Export auf Getter statt auf Klasse zu setzen. Ich werde es testen und Sie wissen lassen, ob dadurch das Problem behoben wird. –