通过AttributeedModelPrograming,我们可以声明暴露组件,依赖组件,发现组件,但是所有这些需要有一个触发点。即需要把所有这些组合在一起来协同工作,最终实现依赖注入。这就是Container层所做的事情.

CompositionContainer            

CompositionContainer在MEF中负责组合其他元素来实现依赖注入。看看他的一个构造函数:

public CompositionContainer(
ComposablePartCatalog catalog,//指明如何发现组件
bool isThreadSafe,//指明是否需要线程安全,这个如果在多线程模型下需要设为true
params ExportProvider[] providers
)

可以看出,我们把Catalog传入container,即告诉了container如何去发现组件,再结合通过Export/Import各种attributes定义好的依赖模型。不难理解container已经可以去根据依赖模型注入依赖了。接下来就是触发点。Container提供了一系列API来填充给定组件中的依赖。主要是如下几个:

Compose(CompositionBatch)

Adds or removes the parts in the specified CompositionBatch from the container and executes composition.

     
GetExportedValue<T>()

Returns the exported object with the contract name derived from the specified type parameter. If there is not exactly one matching exported object, an exception is thrown.(Inherited fromExportProvider.)

GetExportedValue<T>(String)

Returns the exported object with the specified contract name. If there is not exactly one matching exported object, an exception is thrown.(Inherited from ExportProvider.)

     
SatisfyImportsOnce(ComposablePart)

Satisfies the imports of the specified ComposablePart object without registering it for recomposition.(当前组件不会被注册为Export组件)

     

然后在AttributedModelService中提供了一系列面向组件实例的API,常用的Extension方法有如下几个:

     
ComposeParts(CompositionContainer, Object[])

Creates composable parts from an array of attributed objects and composes them in the specified composition container.

     
CreatePart(Object)

Creates a composable part from the specified attributed object.

     
SatisfyImportsOnce(ICompositionService, Object)

Composes the specified part by using the specified composition service, with recomposition disabled.

     

ExportProvider          

其实到这里似乎可以认为,Container负责了实际组件对象的创建。因为Catalog只定义了组件的发现,然后生成PartDefinition。但其实真实情况不是这样,Container其实这是个接口层,真正负责组件实例的创建是由第一篇中的那幅图中还没有用过的ExportProvider来负责。看看ExportProvider的接口定义:

看上去有很多方法,其实都是在做一件事,根据ImportDefinition来得到一个Export对象(组件实例的包装)

内置的ExportProvider有如下几种:

CompositionContainer - CompositionContainer自身其实也是一种ExportProvider

MutableExportProvider - 当创建CompositionContainer时,Container内部会创建该ExportProvider,然后负责管理通过调用Container接口手动添加的组件

ComposablePartCatalogExportProvider - 它负责管理通过PartCatalog发现的组件,当创建CompositionContainer的时候如果传入了Catalog,Container会创建该ExportProvider.

AggregatingExportProvider - 根据名字即可知道,该ExportProvider是用来组合其他ExportProvider的,上述创建CompositionContainer的时候创建的ExportProvider最后都会聚合在该Provier中统一管理。

也可以自定义ExportProvider,然后创建CompositionContainer的时候加入到Container中,则可以对MEF进行扩展。

Recomposition            

在依赖的组件已经注入之后,如果后续对Export的组件进行添加和删除后,想要更新原来已经注入的依赖组件。则可以使用Recomposition。看如下代码:

public interface ILog
{ } [Export(typeof(ILog))]
[ExportMetadata("Type", "file")]
public class FileLog : ILog
{ } [Export(typeof(ILog))]
[ExportMetadata("Type", "db")]
public class DBLog : ILog
{ } public class TaskExecutor
{
[ImportMany(typeof(ILog), AllowRecomposition = true)]
public IEnumerable<ILog> _loggers;
} class Program
{ static void Main(string[] args)
{ var container = new CompositionContainer(new TypeCatalog(typeof(DBLog))); var taskExecutor = new TaskExecutor();
container.ComposeParts(taskExecutor); Console.WriteLine(taskExecutor._loggers.Count());//此时只有DBLog满足注入条件因此logger的个数为1 var fileLog = new FileLog();
var fileLogPart = AttributedModelServices.CreatePart(fileLog);
var partBatch = new CompositionBatch();
partBatch.AddPart(fileLogPart);//添加FileLog满足ILog的注入条件 container.Compose(partBatch); Console.WriteLine(taskExecutor._loggers.Count());//Recomposition会更新logger的注入依赖,此时的logger个数为2 Console.ReadKey();
}
}

MEF学习总结(4)---Container层的更多相关文章

  1. MEF学习总结(2)---Primitive层

    Primitive层是属于依赖注入的通用模型,主要有如下核心类型: 1. ComposablePart是核心类,他表示组件容器中的每一个组件,是对真正组件实例的包装.ExportDefinition属 ...

  2. C#可扩展编程之MEF学习笔记(五):MEF高级进阶

    好久没有写博客了,今天抽空继续写MEF系列的文章.有园友提出这种系列的文章要做个目录,看起来方便,所以就抽空做了一个,放到每篇文章的最后. 前面四篇讲了MEF的基础知识,学完了前四篇,MEF中比较常用 ...

  3. C#可扩展编程之MEF学习笔记(四):见证奇迹的时刻

    前面三篇讲了MEF的基础和基本到导入导出方法,下面就是见证MEF真正魅力所在的时刻.如果没有看过前面的文章,请到我的博客首页查看. 前面我们都是在一个项目中写了一个类来测试的,但实际开发中,我们往往要 ...

  4. C#可扩展编程之MEF学习笔记(三):导出类的方法和属性

    前面说完了导入和导出的几种方法,如果大家细心的话会注意到前面我们导出的都是类,那么方法和属性能不能导出呢???答案是肯定的,下面就来说下MEF是如何导出方法和属性的. 还是前面的代码,第二篇中已经提供 ...

  5. C#可扩展编程之MEF学习笔记(二):MEF的导出(Export)和导入(Import)

    上一篇学习完了MEF的基础知识,编写了一个简单的DEMO,接下来接着上篇的内容继续学习,如果没有看过上一篇的内容, 请阅读:http://www.cnblogs.com/yunfeifei/p/392 ...

  6. C#可扩展编程之MEF学习笔记(一):MEF简介及简单的Demo

    在文章开始之前,首先简单介绍一下什么是MEF,MEF,全称Managed Extensibility Framework(托管可扩展框架).单从名字我们不难发现:MEF是专门致力于解决扩展性问题的框架 ...

  7. MEF学习总结(3)---Attribute Model Programing

    上一片介绍了Primitive层,Attribute Model可以认为是对Primitive的上层实现.主要包括如下内容: 1. 一系列的Attribute来定义Import和Export 常用的有 ...

  8. MEF学习总结(1)---总体架构

    用了很久的MEF框架来做依赖注入,最近想把它的原理和机构总结一下,主要包括如下几个方面: 1. 总体架构 2. .Net Composition Primitive 3. Attribute Mode ...

  9. C#可扩展编程之MEF学习

    MEF系列文章: C#可扩展编程之MEF学习笔记(一):MEF简介及简单的Demo C#可扩展编程之MEF学习笔记(二):MEF的导出(Export)和导入(Import) C#可扩展编程之MEF学习 ...

随机推荐

  1. Zeratul的完美区间(线段树||RMQ模板题)

    原题大意:原题链接 给定元素无重复数组,查询给定区间内元素是否连续 解体思路:由于无重复元素,所以如果区间内元素连续,则该区间内的最大值和最小值之差应该等于区间长度(r-l) 解法一:线段树(模板题) ...

  2. Java SHA256/Base64转.NET(C#)实现---(华为云云市场.NET版本加密方式)

    前言: 工作需要,对接华为云应用市场的 API 接口,由于维护团队都是 .NET 所以用 .NET 来开发. 简单了解一下 SHA256 加密算法,本质就是一个 Hash,与 MD5 相比就是计算量大 ...

  3. 最近玩了一下qt5.2.1,顺着写点东西,关于这个版本设置程序主窗口居中

    #include <QtGui/QGuiApplication> #include <QDebug> #include <QScreen> #include &qu ...

  4. Quartz 框架 教程(中文版)2.2.x

    Quartz 框架 教程(中文版)2.2.x 之第一课 开始使用Quartz框架 Quartz 框架 教程(中文版)2.2.x 之第二课 Quartz API,Jobs和Triggers简介 Quar ...

  5. hdu2732

    题解: 和上一题差不多 然后注意格式 代码: #include<cstdio> #include<cmath> #include<algorithm> #inclu ...

  6. Falsk项目cookie中的 csrf_token 和表单中的 csrf_token实现

    Flask中请求体的请求开启CSRF保护可以按以下配置 from flask_wtf.csrf import CSRFProtect app.config.from_object(Config) CS ...

  7. 2017北京赛区H题

    题目链接 题意:在n*m的矩阵中选择变换或者不变换一个数变成p,使得最大子矩阵和最小 1<=n,m<=150, -1000<=p<=1000; 题解: 他人题解链接 涉及到知识 ...

  8. [转载]Spring源码下载地址

    转载自:http://blog.csdn.net/liuzheng2684/article/details/6534722,谢谢! 今天想下载一下spring的源代码,登录到Spring官网,傻眼了, ...

  9. 继承users表,添加新字段成一个新表

    1. Tools > Run manage.py Task 创建app,users startapp users 2.修改users中的models from django.db import ...

  10. (转)MapReduce Design Patterns(chapter 3 (part 1))(五)

    Chapter 3. Filtering Patterns 本章的模式有一个共同点:不会改变原来的记录.这种模式是找到一个数据的子集,或者更小,例如取前十条,或者很大,例如结果去重.这种过滤器模式跟前 ...