MEF的对象破坏问题

时间:2010-12-06 15:54:36

标签: c# mef destructor

我使用静态变量来保存对象的数量。在构造函数中,我增加了这个变量。这样我知道创建了多少个对象实例。 使用这些对象后,它们会被解除引用。 我怀疑MEF是否持有对这些对象的引用,因此我强制GC进行清理(使用GC.Collect()方法)。我希望在下一个对象创建时,这个变量从零开始,但它从最后一个数字开始重新开始。我在destructor中放置了一个日志记录机制用于跟踪,只有在应用程序关闭后才会销毁对象。 我可以假设MEF已经创建了对这些对象的其他引用吗?

我使用MEFExportFactory来创建我的对象

编辑:

也许应该使用ExportLifetimeContext的某些内容?

4 个答案:

答案 0 :(得分:8)

  

我强制GC进行清理

如果MEF仍然有对象的引用,那么显然这没有做任何事情。如果对象变成了垃圾,那么垃圾收集器会自动收集它们 - 要求它明确地执行它只是一个可能被忽略的提示。无论哪种方式,这都没有必要。

  

我在析构函数中放置了一个用于跟踪的日志记录机制,只有在关闭应用程序后才会销毁对象。我可以假设MEF已经创建了对这些对象的其他引用吗?

MEF将保留对已创建对象的引用,以便在您请求导出时能够重复返回相同的引用。要让MEF放弃这些引用,您应该致电CompositionContainer.Dispose。显然,在此之后你不能再重复使用容器,尽管你可以创建一个新容器。

MEF也是它创建的任何IDisposable个对象的所有者。这意味着当您处置容器时,它会在放弃引用之前在任何此类对象上调用Dispose

最好依靠对Dispose的调用来执行清理,而不是使用终结器。 There is no guarantee that finalizers are run at all

修改

  

我需要在使用它之后销毁它。但我不想破坏容器。我希望MEF作为工厂来创建询问部件的新实例,并且调用者应该能够在他不再需要时销毁该对象。你能帮帮忙吗?

这是ExportFactory的用途。 (以前称为PartCreator)。遗憾的是,除非您使用Silverlight,否则它在.NET 4中尚不可用。您可以使用codeplex的预览版本试一试。

如果您不想使用MEF的预览版本,您可以通过创建包装容器的工厂类并使用其ExportFactory和<来自己实现GetExport之类的内容。 strong> ReleaseExport 获取和释放对象的方法。如果您需要创建同一部件的多个实例,请不要忘记设置PartCreationPolicy

编辑2: 我不知何故错过了你一直在使用ExportFactory。完成对象后,您只需要调用ExportLifeTimeContext.Dispose

答案 1 :(得分:1)

CLR中对象的及时“破坏”(即最终确定)并不是一件好事。如果您是出于调试目的而这样做,则没有必要。您可以按照我对此问题的回答中的说明找出某些类型的对象仍然存在的数量:

Memory Leaks in C# WPF

如果您真的试图让您的软件行为取决于GC未回收的类实例数,那么您需要重新考虑您的设计。有几种更好的方法可以达到你想要的效果。

答案 2 :(得分:1)

对于共享对象,只要容器处于活动状态,MEF就会保留对它们的引用。您可以在适当的情况下尽早处理非共享部件。如果您正在使用ExportFactory,则需要处理CreateExport方法返回的ExportLifetimeContext以处置作为请求的一部分创建的任何NonShared部件。如果在容器上调用了GetExport方法,则可以调用ReleaseExport方法。如果您以其他方式获得导出(即SatisfyImports或其他方式),则无法释放它们,因此您可能希望重构您的应用程序以使用ExportFactory或GetExport。

答案 3 :(得分:0)

MEF现在有一个支持ExportFactory的桌面版本。虽然名称有“导出”字样,但您应该在执行“导入”的位置实现它。调用CreateExport()方法创建零件的新实例将返回ExportLifetimeContext<T>此对象具有Dispose()方法,稍后可用于释放导出的对象。此方法会自动调用您的对象Dispose(),您无需手动调用它。

这种行为是因为容器本身就是创建对象的所有者,即使引用了这些对象,调用它们Dispose()对它们也没有影响。