我在WPF应用程序中使用MEF。我使用MEF为我的视图创建视图模型对象,并且通过确保MEF CompositionContainer
不保留对我的视图模型对象的引用来对避免内存泄漏感兴趣。
我知道this question及其答案。我谨慎地避免使用IDisposable
,因为it doesn't "play nicely" with WPF。
出于调试目的,我想编写一些声明某个对象尚未添加到CompositionContainer
的代码。这将确保我没有对视图模型类进行微妙的更改,这意味着它现在没有被正确释放。
以下是一些示例代码。我该如何实施AssertNotInContainer
?请注意,在此示例中,正确处置exportLifetimeContext
将是微不足道的。但是,在我更复杂的场景中,我希望能够依赖垃圾收集器而不是IDisposable
,因为it is hard to determine the lifetime of WPF objects and their associated view models(由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文档包含一个有用但过时的page explaining the lifetime of objects created by MEF。它说:
我们相信.Net垃圾收集器是最好的依靠正确清理。但是,我们还需要提供具有确定性行为的容器。因此,除非满足下列条件之一,否则容器将不会保留对其创建的零件的引用:
- 该部件标记为共享
- 该部分实现了
IDisposable
- 配置一个或多个导入以允许重新组合