通过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. 变更Linux下的Java版本 alternatives

    默认正常情况下,即使使用Java 1.6版本Java脚本jdk-6u31-linux-i586.bin,安装Java运行后,会出现自动升级为1.7版本状态的情况.针对某些应用程序需要基于1.6版本方可 ...

  2. Python内置函数详解-总结篇

    参考链接:http://www.cnblogs.com/sesshoumaru/p/6140987.html

  3. 跨域问题Java方式解决及Nginx方式解决【亲测可行】

    这两天和前端同事调试微信公众号项目,就遇到了跨域问题:网上相关博客也挺多的,但有很多细节没有点到,在此呢我也再次记录一下解决方式: (算是踩坑日记吧~ ~ ~)   !问题发现: 页面加载不出来,控制 ...

  4. CMDB配置资源管理数据库(理解)

    CMDB是运维自动化的基础,它为日志系统,发布系统,监控系统等运维系统(ELK,zabbix,open-falcon)提供接口函数, 第一种方式:Agent方法实现,agent不能直接访问数据库,因为 ...

  5. django中如何将多个app归到一个目录下。

    1.当startapps 生成多个app后,为了便于管理,可新建一个apps目录,把应用全部剪切进apps. 如果是在pycharm中,会提示是否自动更新路径,这里要全部选择取消. QQ群交流:697 ...

  6. Redis数据库的学习及与python的交互

    1. 数据库简介: 当前主要使用两种类型的数据库:关系型数据库(RDBMS).非关系型数据库(NoSQL); (1). 关系型数据库RDBMS: 是建立在关系模型基础上的数据库,借助于集合代数等数学概 ...

  7. MoreEffectiveC++Item35(操作符)(条款5-8)

    条款5 对定制的"类型转换函数"保持警惕 条款6 区别increment/decrement操作符的前值和后置形式 条款7 千万不要重载&&,||,和,操作符 条款 ...

  8. JQ上传预览+存数据库

    因为之前老师讲的方法有不少BUG 现在经过完善已经修复 之前老是讲的方法是每一张都会被传到后台文件夹里面去 导致在预览过程中如果刷新页面 那么预览的图片不能从后台文件夹中删除  这个方法实现在本地预览 ...

  9. 用JQuery怎么去一次性获取 aspTextBox 文本框的值

    如:<asp:TextBox ID="txtSubject" runat="server">aa</asp:TextBox> 第一次用服 ...

  10. BDD测试框架Spock概要

    前言 为了找到一个适合自己的.更具操作性的.以DDD为核心的开发方法,我最近一直在摸索如何揉合BDD与DDD.围绕这个目标,我找到了Impact Mapping → Cucumber → Spock ...