如何从MEF容器中释放共享实例

时间:2011-03-25 14:00:06

标签: c# mef

我正在尝试释放共享实例或单例值。有谁知道如何做到这一点?我是否需要刷新目录?我正在学习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将拥有新值。

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

2 个答案:

答案 0 :(得分:3)

默认情况下,在MEF中,创建导出时,会共享。在许多其他容器中,这被称为Singleton生活方式。这意味着释放导出将不会执行任何操作,因为容器需要为其他潜在消费者挂起导出。

你面前有两个选项:

  1. 假设您完成了容器,请处置容器。例如,当应用程序关闭时,这是合适的。
  2. 将您的零件更改为临时对象,即每次从容器请求零件时都会创建一个新零件。要在MEF中执行此操作,请将PartCreationPolicy属性添加到Export,并指定它是非共享的。这看起来像这样:[PartCreationPolicy (CreationPolicy.NonShared)]。这将导致在调用Dispose时在您的部件上调用container.ReleaseExport(myExport)方法,其中myExport是一个导出(不是导出的值),保留到释放目的。
  3. 以下是一个例子:

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

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

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

答案 1 :(得分:0)

由于您使用的是Shared创建策略,因此容器将保留对创建的部分的引用。释放零件的方法是从容器中获取包含的导出,然后释放。

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

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