【问题标题】:MEF ExportFactory<T> - How to properly dispose in a long-running application?MEF ExportFactory<T> - 如何在长时间运行的应用程序中正确处理?
【发布时间】:2011-07-01 12:54:27
【问题描述】:

基本上,有没有一种简单的方法来处理由ExportFactory&lt;T&gt; 创建的导入?我问的原因是因为导出通常包含对仍然存在的东西的引用,例如 EventAggregator。我不想遇到这样的问题:我创建了数百个这样的东西,并在不需要时让它们闲置。

我注意到,当我创建对象时,我会返回一个带有 Dispose 的 ExportLifetimeContext&lt;T&gt;。但是,我不想将 ExportLifetimeContext 传回我的 ViewModel 请求 ViewModel 的副本,因此我将值传回。 (return Factory.Single(v =&gt; v.Metadata.Name.Equals(name)).CreateExport().Value;)

【问题讨论】:

    标签: c# memory-management mef factory object-lifetime


    【解决方案1】:

    当您在ExportLifetimeContext&lt;T&gt; 上调用Dispose 时,它将在T 创建所涉及的任何NonShared 部分上调用dispose。它不会处理任何Shared 组件。这是一种安全的行为,因为如果 NonShared 部分被实例化纯粹是为了满足 T 的导入,那么它们可以安全地被处置,因为它们不会被任何其他导入使用。

    我认为您可以实现它的唯一其他方法是自定义 Dispose 方法以将 dispose 调用链接到您导入的任何其他成员属性,例如:

    [Export(typeof(IFoo))]
    public class Foo : IFoo, IDisposable
    {
        [Import]
        public IBar Bar { get; set; }
    
        public void Dispose()
        {
            var barDisposable = Bar as IDisposable;
            if (barDisposable != null) 
                barDisposable.Dispose();
        }
    }
    

    但是因为您的类型不知道IBar 的导入实例是Shared 还是NonShared,所以您冒着处置共享组件的风险。

    我认为挂在ExportedLifetimeContext&lt;T&gt; 的实例上是实现你想要的唯一安全的方法。

    不确定这是否有帮助,感觉像是不必要的包装,但你能不能:

    public class ExportWrapper<T> : IDisposable
    {
      private readonly ExportLifetimeContext<T> context;
    
      public ExportWrapper<T>(ExportLifetimeContext<T> context)
      {
        this.context = context;
      }
    
      public T Value 
      {
        get { return context.Value; }
      }
    
      public void Dispose()
      {
        context.Dispose();
      }
    
      public static implicit operator T(ExportWrapper<T> wrapper)
      {
        return wrapper.Value;
      }
    
      public static implicit operator ExportWrapper<T>(ExportLifetimeContext<T> context)
      {
        return new ExportWrapper<T>(context);
      }
    }
    

    你可能:

    [Import(typeof(IBar))]
    public ExportFactory<IBar> BarFactory { get; set; }
    
    public void DoSomethingWithBar()
    {
      using (ExportWrapper<IBar> wrapper = BarFactory.CreateExport())
      {
        IBar value = wrapper;
        // Do something with IBar;
        // IBar and NonShared imports will be disposed of after this call finishes.
      }
    }
    

    感觉有点脏……

    【讨论】:

    • 你打败了我回答我自己的问题。实际上,我创建了一个抽象的ExportFactoryController&lt;T, TMetadata&gt; 和一个 IExportFactoryController` 来保存部件创建的字典和ExportLifetimeContext&lt;T&gt;s。然后,我公开 Dispose(T 部分),它从字典中找到上下文并处理它/从字典中删除它。我还有一个 DisposeAll(),它处理存储在字典中的所有上下文并清除字典缓存。唯一烦人的是我的ImportMany 很平淡:[ImportMany] IEnumerable&lt;ExportFactory&lt;T, TMetadata&gt;&gt; Factories;
    猜你喜欢
    • 1970-01-01
    • 2016-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-04
    • 2012-02-01
    • 1970-01-01
    • 2010-10-28
    相关资源
    最近更新 更多