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

5
我想释放一个共享实例或单例值。有人知道如何做吗?我需要刷新目录吗?我正在学习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个回答

4
默认情况下,在MEF中创建Export时,它是共享的。在许多其他容器中,这称为Singleton生命周期。这意味着释放导出将无效,因为容器需要保留导出以供其他潜在消费者使用。
您真正面临两个选择:
1. 释放容器,假设您已经完成了它。例如,当应用程序关闭时,这是适当的选择。 2. 将您的部件更改为瞬态对象,即每次从容器请求一个新部件都会创建一个新的实例。要在MEF中实现此操作,请向导出添加PartCreationPolicy属性,并指定其为非共享。如下所示:[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容器的地方以及保留对导出内容的引用的地方执行此操作。

然而请注意,将单例对象更改为瞬态对象将会影响容器的性能,因为反射会被用来创建每个新对象。


0

因为您正在使用Shared创建策略,容器将保留对已创建部件的引用。要释放该部件,您可以从容器中获取包含导出项,然后进行释放。

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

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


5
这并不会实际释放该部件。共享的部件直到其所在的容器被处理掉之前都不会被释放。调用 ReleaseExport 只会释放非共享的部件(以及为它们创建的任何非共享依赖项)。 - Daniel Plaisted

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接