我使用 MEF 将接口映射到实现类作为 DI 的一种方式。例如,我将 Import 属性用于接口,将 Export 用于实现类。我的理解是MEF框架将创建实现类实例并将它们保存在MEF的容器中以供使用或自动注入。
我的一些实现类实现了 IDispose 接口。由于实例是由 MEF 创建的,我认为我应该让 MEF 调用组件的 Dispose 方法,如果它们在 MEF 退出时是一次性的。例如,在我的应用程序中,我持有对 MEF 容器的引用。当应用程序终止时,我调用容器的 Dispose 方法。问题是我的组件的 Dispose 从未被调用。
下面是一些关于导入和导出映射的示例代码:
[Import]
private IMyInterface IComponent1 { get; set; }
....
[Export]
private IMyInterface Component {
get {
var instance = new MyImplemetation();
....
return instance;
}
}
....
以类似的方式还有许多其他映射的其他导入和导出定义。我以这种方式构造映射,以便 MEF 了解关系以及如何创建映射实例的方式。以下是我的应用程序中使用 AssemblyCatalog 加载映射的一些代码:
var catalog = new AggregateCatalog();
catalog.Add (new AssemblyCatalog(Assembly.GetExecutingAssembly());
var batch = new CompositionBatch();
batch.AddPart(catalog);
// MEF container has all the mappings
var container = new CompositionContainer(catalog);
....
// Get instance from container
var instance = container.GetExportedValue<IMyInterface>();
// my instance CTOR has a contructor with several other
// implementation instances injected by interface
// instance starts to do its job and coordinates others ...
instance.Start();
....
// Finally the job is done.
// Dispose the container explicitly there.
container.Dispose();
// But my components are never disposed
// this results some connections not being closed
// file streams not being closed...
这里的实例有许多其他由 MEF 通过 CTOR 注入的组件。这些组件还包含由 MEF 注入的其他组件。问题在于,由于某些实例是共享的,因此很难决定何时处置组件。如果我在其中一个上调用 Dispose,这将导致其他人无法使用它。正如您在这张图片中看到的,实例由 MEF 创建并注入到我的应用程序类中。每个组件不应该对其他组件有任何了解,并且应该使用注入的组件来完成工作。
我不确定当应用程序终止或容器被处置时,我应该在哪里/如何指示 MEF 在组件上调用 Dispose?我应该在组件上调用 Dispose 吗?我认为这是不对的,因为 MEF 创建它们并根据需要将它们注入客户端。客户在完成工作时不应调用他们的 Dispose。