1

我在 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
  • 一个或多个导入配置为允许重组
4

0 回答 0