c# - 通过 MEF 容器处理组件?

标签 c# mef

我使用 MEF 将接口(interface)映射到实现类作为 DI 的一种方式。例如,我对接口(interface)使用 Import 属性,对实现类使用 Export 属性。我的理解是 MEF 框架将创建实现类实例并将它们保存在 MEF 的容器中以供使用或自动注入(inject)。

我的一些实现类实现了 IDispose 接口(interface)。由于实例是由 MEF 创建的,我想我应该让 MEF 在 MEF 退出时调用组件的 Dispose 方法(如果它们是一次性的)。例如,在我的应用程序中,我持有对 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 注入(inject)。这些组件还包含由 MEF 注入(inject)的其他组件。问题在于,由于某些实例是共享的,因此很难决定何时处置组件。如果我对一个调用 Dispose,这将导致其他人无法使用它。正如您在此图片中看到的,实例由 MEF 创建并注入(inject)到我的应用程序类中。每个组件都不应该知道其他组件,并且应该使用注入(inject)的组件来完成这项工作。

我不确定当应用程序终止或容器被处置时,我应该在哪里/如何指示 MEF 在组件上调用 Dispose?我应该在组件上调用 Dispose 吗?我认为这是不对的,因为 MEF 创建它们并根据需要将它们注入(inject)客户端。客户在完成工作时不应该调用他们的 Dispose。

最佳答案

MEF 确实管理它创建的组件的生命周期。看起来你的例子中的问题是你想要处理的对象实际上不是由 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,然后对所有请求使用同一个。

关于c# - 通过 MEF 容器处理组件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2328471/

相关文章:

c# - 如何启动 WCF 语音聊天应用程序?

asp.net-mvc - 我们如何使用 ASP.NET MVC 4 和 MEF 2 支持模块化和可测试模式?

c# - 了解 MEF System.Lazy<T,TMetaData>

c# - MEF 和序列化

.net - 为什么使用 ImportingConstructor 属性?

.net - MEF是否可以替代System.Addin?

javascript - 在C#中通过JS发布解密RSA公钥加密数据

c# - 如何添加对列表的引用

c# - 禁用文本框显示其中键入的旧数据的能力

c# - 提高 .NET/MSSQL 选择和更新性能