加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 由MEF容器处理组件?

发布时间:2020-12-15 06:51:16 所属栏目:百科 来源:网络整理
导读:我使用MEF将接口映射到实现类作为DI的一种方式.例如,我使用导入属性作为接口,导出为实现类.我的理解是,MEF框架将创建实现类实例并将它们保存在MEF的容器中以供使用或自动注入. 我的一些实现类实现了IDispose接口.由于实例是由MEF创建的,我想我应该让MEF调用
我使用MEF将接口映射到实现类作为DI的一种方式.例如,我使用导入属性作为接口,导出为实现类.我的理解是,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...

这里的实例有许多其他组件通过CTOR通过MEF注入.这些组件还包含由MEF注入的其他组件.问题在于,由于某些实例被共享,因此很难决定何时配置组件.如果我打电话给Dispose,这将导致其他人无法使用它.如图所示,实例由MEF创建并注入到我的应用程序类中.每个组件不应该有其他知识,应该使用注入组件来完成这项工作.

我不知道在应用程序终止或容器处理时,我应该如何指示MEF在组件上调用Dispose?我应该在组件上调用Dispose吗?我认为这是正确的,因为MEF创建它们并将其注入客户端.客户在完成工作时不应该打电话给他们.

解决方法

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,然后对所有请求使用相同的请求.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读