如何从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将拥有新值。

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

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

你面前有2个选项:

  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 myExport = container.GetExport(); // later on... container.ReleaseExport(myExport) 

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

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

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

 var export = container.GetExport(); container.ReleaseExport(export); 

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