【问题标题】:How to release a shared instance from a MEF container如何从 MEF 容器中释放共享实例
【发布时间】:2013-10-15 20:17:31
【问题描述】:

我正在尝试释放共享实例或单例值。有谁知道如何做到这一点?我必须刷新目录吗?我正在学习 MEF,所以请帮忙。

类示例

[Export]
public class Foo
{
  public RandomProperty {get;set;}

  [ImportConstructor]
  public Foo() {}
}

你可以用这样的东西来创建它:

var fooSingleton = ServiceLocator.GetInstance(typeof(Foo));

一切都很好,但理想情况下我想做这样的事情

Container.Replace(oldFoo, newFoo);

所以当我再次调用它时

var fooSingleton = ServiceLocator.GetInstance(typeof(Foo));

fooSingleton 将具有新值。

我认为答案可能取决于实际清除目录然后刷新它 - 但对于这么简单的事情来说这似乎有点过分了。

【问题讨论】:

    标签: c# mef


    【解决方案1】:

    默认情况下,在 MEF 中,当您创建导出时,它是共享的。在许多其他容器中,这被称为 Singleton 生活方式。这意味着释放导出将无济于事,因为容器需要为其他潜在消费者保留导出。

    你真的有两个选择:

    1. 假设您已完成容器,请丢弃该容器。这适用于应用程序关闭等情况。
    2. 将您的部件更改为临时对象,即每次您从容器请求一个新部件时都会创建一个新部件。要在 MEF 中执行此操作,请将 PartCreationPolicy 属性添加到 Export 并指定它是非共享的。这看起来像这样:[PartCreationPolicy (CreationPolicy.NonShared)]。这将导致在调用 container.ReleaseExport(myExport) 时在您的部件上调用 Dispose 方法,其中 myExport 是一个导出(不是导出值),用于发布目的。

    这是一个例子:

    var catalog = new AggregateCatalog(// code elided);
    var container = new CompositionContainer(catalog);
    
    Lazy<IMyExportInterface> myExport = container.GetExport<IMyExportInterface>();
    // later on...
    container.ReleaseExport(myExport)
    

    这表明您需要在可以访问 MEF 容器的地方执行此操作,并且您保留了对导出的引用。

    但是,请小心。更改为瞬态对象而不是单例将影响容器的性能,因为反射用于创建每个新对象。

    【讨论】:

      【解决方案2】:

      因为您使用的是Shared 创建策略,所以容器将保留对所创建部件的引用。释放部件可以做的是从容器中获取包含的导出,然后释放。

      var export = container.GetExport<Foo>();
      container.ReleaseExport(export);
      

      您可能需要更新您的消费类型(Imports 所在的位置),以支持重组。

      【讨论】:

      • 这实际上不会发布该部分。在容器本身被处置之前,共享部件根本不会被释放。 ReleaseExport 将仅发布非共享部分(以及为它们创建的任何非共享依赖项)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-14
      • 1970-01-01
      • 2018-12-14
      • 1970-01-01
      • 2017-12-16
      相关资源
      最近更新 更多