我在 WPF 应用程序中使用 MEF。我使用 MEF 为我的视图创建视图模型对象,并且有兴趣通过确保 MEFCompositionContainer
不保留对我的视图模型对象的引用来避免内存泄漏。
我知道这个问题及其答案。我小心避免使用IDisposable
,因为它不能与 WPF “很好地配合”。
出于调试目的,我想编写一些代码来断言尚未将对象添加到CompositionContainer
. 这将确保我没有对视图模型类进行细微更改,这意味着它现在没有正确发布。
这是一些示例代码。我该如何实施AssertNotInContainer
?请注意,在此示例中,正确处理将是微不足道的exportLifetimeContext
。但是,在我更复杂的场景中,我希望能够依赖垃圾收集器而不是IDisposable
,因为很难确定 WPF 对象及其关联视图模型(由 附加DataContext
)的生命周期。
namespace Demo
{
using System;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Diagnostics;
class Program
{
static void Main(string[] args)
{
CompositionContainer container = new CompositionContainer(new ApplicationCatalog());
MyOwnerClass demo = container.GetExport<MyOwnerClass>().Value;
// Not going to dispose this...
ExportLifetimeContext<MyLittleClass> exportLifetimeContext = demo.Factory.CreateExport();
// Note that I don't dispose of exportLifetimeContext, since I know that if MyLittleClass obeys
// the proper rules, it won't be added to the container anyway, and exportLifetimeContext.Dispose()
// will do nothing anyway.
MyLittleClass part = exportLifetimeContext.Value;
// I wan't this to assert that part is not referenced in container.
container.AssertNotInContainer(part);
// This is a hacky way that I can confirm that MyLittleClass isn't referenced by the container.
// This causes "Finalized." to be sent to the console.
GC.Collect();
Console.ReadLine();
}
}
[Export]
public class MyOwnerClass
{
[Import]
public ExportFactory<MyLittleClass> Factory { get; set; }
}
[Export]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class MyLittleClass
{
~MyLittleClass()
{
Console.WriteLine("Finalized.");
}
}
public static class MefHelper
{
[Conditional("DEBUG")]
public static void AssertNotInContainer(this CompositionContainer container, object part)
{
// What code should I write here?
bool isInContainer = false /* ??? */;
if (isInContainer)
{
throw new InvalidOperationException(
"Part does not meet rules for not being added to CompositionContainer. You have a leak!");
}
}
}
}
MEF 零件寿命
MEF 文档包含一个有用但已过时的页面,该页面解释了 MEF 创建的对象的生命周期。它说:
我们相信 .Net 垃圾收集器是进行适当清理的最佳选择。但是,我们还需要提供一个具有确定性行为的容器。因此,除非满足以下条件之一,否则容器不会保存对其创建的部件的引用:
- 该部件被标记为共享
- 该部分实现
IDisposable
- 一个或多个导入配置为允许重组