我的一些实现类实现了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...
这里的实例有许多其他组件通过CTOR通过MEF注入.这些组件还包含由MEF注入的其他组件.问题在于,由于某些实例被共享,因此很难决定何时配置组件.如果我打电话给Dispose,这将导致其他人无法使用它.如图所示,实例由MEF创建并注入到我的应用程序类中.每个组件不应该有其他知识,应该使用注入组件来完成这项工作.
我不知道在应用程序终止或容器处理时,我应该如何指示MEF在组件上调用Dispose?我应该在组件上调用Dispose吗?我认为这是正确的,因为MEF创建它们并将其注入客户端.客户在完成工作时不应该打电话给他们.
解决方法
public class ComponentExporter : IDisposable { private IMyInterface _component; [Export] public IMyInterface Component { get { if (_component != null) { _component = new MyImplementation(); // ... } return _component; } } public void Dispose() { if (_component != null) { _component.Dispose(); } } }
ComponentExporter是由MEF实际创建的类,如果它实现了IDisposable,则MEF将使用该容器进行处理.在此示例中,ComponentExporter在处理时处理已创建的组件,这很可能是您想要的.
当然,如果您直接将导出导出到MyImplementation类,那将会更容易.我假设你有一些理由不这样做,但这是它的外观:
[Export(typeof(IMyInterface))] public class MyImplementation : IMyInterface,IDisposable { // ... }
关于代码的其他一些注意事项:您可能不需要通过批处理将目录添加到容器中,除非您将其导入到某个位置并从容器内的部分进行修改.而且,如果您正在处理许多请求并且关心性能,那么您只应该创建一次AssemblyCatalog,然后对所有请求使用相同的请求.