【问题标题】:Object destruction problem with MEFMEF 的对象破坏问题
【发布时间】:2010-12-06 15:54:35
【问题描述】:

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

我使用MEFExportFactory 来创建我的对象

编辑:

也许应该用ExportLifetimeContext 做点什么?

【问题讨论】:

    标签: c# mef destructor


    【解决方案1】:

    我强制 GC 进行清理

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

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

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

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

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

    编辑:

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

    这就是ExportFactory 的用途。 (以前称为PartCreator)。不幸的是,它在 .NET 4 中尚不可用,除非您使用 Silverlight。您可以使用来自codeplex 的预览版来试一试。

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

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

    【讨论】:

    • 我需要在使用后销毁该对象。但我不想破坏容器。我希望 MEF 作为创建请求部分的新实例的工厂,并且调用者应该能够在他不再需要时销毁该对象。你能帮忙吗?
    • 现在从 codeplex 支持 ExportFactory。有用的答案和我为这个问题添加的答案的线索。 +1
    【解决方案2】:

    CLR 中对象的及时“销毁”(即终结)并不是一件值得依赖的好事情。如果您这样做是出于调试目的,则没有必要。按照我对这个问题的回答中的说明,您可以找出仍然存在多少某种类型的对象:

    Memory Leaks in C# WPF

    如果您真的想使您的软件的行为依赖于尚未被 GC 回收的类的实例数的计数,那么您需要重新考虑您的设计。将有几种更好的方法来实现您想要的。

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        MEF 现在有一个支持ExportFactory 的桌面版本。尽管名称中有“export”字样,但您应该在执行“imports”的地方实现它。调用CreateExport() 方法来创建零件的新实例将返回ExportLifetimeContext<T>,而this 对象有一个Dispose() 方法,该方法稍后可用于释放导出的对象。这个方法会自动调用你的对象Dispose(),你不需要手动调用它。

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-01-24
          • 1970-01-01
          • 2020-08-19
          • 1970-01-01
          • 2010-12-25
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多