MEF学习总结(4)---Container层
通过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层的更多相关文章
- MEF学习总结(2)---Primitive层
Primitive层是属于依赖注入的通用模型,主要有如下核心类型: 1. ComposablePart是核心类,他表示组件容器中的每一个组件,是对真正组件实例的包装.ExportDefinition属 ...
- C#可扩展编程之MEF学习笔记(五):MEF高级进阶
好久没有写博客了,今天抽空继续写MEF系列的文章.有园友提出这种系列的文章要做个目录,看起来方便,所以就抽空做了一个,放到每篇文章的最后. 前面四篇讲了MEF的基础知识,学完了前四篇,MEF中比较常用 ...
- C#可扩展编程之MEF学习笔记(四):见证奇迹的时刻
前面三篇讲了MEF的基础和基本到导入导出方法,下面就是见证MEF真正魅力所在的时刻.如果没有看过前面的文章,请到我的博客首页查看. 前面我们都是在一个项目中写了一个类来测试的,但实际开发中,我们往往要 ...
- C#可扩展编程之MEF学习笔记(三):导出类的方法和属性
前面说完了导入和导出的几种方法,如果大家细心的话会注意到前面我们导出的都是类,那么方法和属性能不能导出呢???答案是肯定的,下面就来说下MEF是如何导出方法和属性的. 还是前面的代码,第二篇中已经提供 ...
- C#可扩展编程之MEF学习笔记(二):MEF的导出(Export)和导入(Import)
上一篇学习完了MEF的基础知识,编写了一个简单的DEMO,接下来接着上篇的内容继续学习,如果没有看过上一篇的内容, 请阅读:http://www.cnblogs.com/yunfeifei/p/392 ...
- C#可扩展编程之MEF学习笔记(一):MEF简介及简单的Demo
在文章开始之前,首先简单介绍一下什么是MEF,MEF,全称Managed Extensibility Framework(托管可扩展框架).单从名字我们不难发现:MEF是专门致力于解决扩展性问题的框架 ...
- MEF学习总结(3)---Attribute Model Programing
上一片介绍了Primitive层,Attribute Model可以认为是对Primitive的上层实现.主要包括如下内容: 1. 一系列的Attribute来定义Import和Export 常用的有 ...
- MEF学习总结(1)---总体架构
用了很久的MEF框架来做依赖注入,最近想把它的原理和机构总结一下,主要包括如下几个方面: 1. 总体架构 2. .Net Composition Primitive 3. Attribute Mode ...
- C#可扩展编程之MEF学习
MEF系列文章: C#可扩展编程之MEF学习笔记(一):MEF简介及简单的Demo C#可扩展编程之MEF学习笔记(二):MEF的导出(Export)和导入(Import) C#可扩展编程之MEF学习 ...
随机推荐
- SVN更新操作提示需要清理操作,清理操作提示乱码,更新SVN失败
1.下载sqlite3.exe,下载方式如下: 1):sqlite网址:https://www.sqlite.org/download.html (根据操作系统自行下载) 2.下载的文件解压后将sql ...
- 到底啥是平台,到底啥是中台?李鬼太多,不得不说(ZT)
(1)哪些不是中台,而是应该叫平台 做开发,有所谓的三层技术架构:前端展示层.中间逻辑层.后端数据层.我们现在讲的中台不在这个维度上. 做开发,还有所谓的技术中间件.一开始我们没有中间件的概念,只有操 ...
- LeetCode OJ:Reorder List(重序链表)
Given a singly linked list L: L0→L1→…→Ln-1→Ln,reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→… You must do thi ...
- AOP的Advice
@Before 方法执行之前执行 @AfterReturning 方法正常执行完成后执行 @AfterThrowing 抛出任何异常之后执行 @After 就是相当于finally,它会将你的方法t ...
- SpringInAction--自动化装配(显示装配之 java注解配置)
Spring在配置时候有三种方案可选 1.在xml中进行显示配置 2.在java中进行显示配置 3.隐式的Bean发现机制和自动装配 今天学习的 第二种—— 在java中进行显示配置 场景: 尽管在很 ...
- New Concept English three(21)
27W 59 Boxing matches were very popular in England two hundred years ago. In those days, boxers foug ...
- vue.js 源代码学习笔记 ----- 工具方法 debug
import config from '../config' import { noop } from 'shared/util' let warn = noop let tip = noop let ...
- three.js入门系列之光和阴影
初中物理教过我们镜面反射和漫反射,这是由于物体的材质直接导致的. 在three.js中,由于物体的材料不同,对于光源的反应也是不一样的,下面就让我们一探究竟. 一.材料 据Three.js中描述,有两 ...
- ubuntu创建Centos7镜像&&配置运行环境
1. 下载centos7镜像 sudo docker pull centos:7 2. 启动centos7容器并挂载本地目录 sudo docker -it -v /home/software:/ho ...
- angular使用遇到的问题
http://www.angularjs.cn/A0a6 用路由的时候,在js里写jquery的事件dom操作失效,只有在子页面里嵌套js才生效(jquery也不行).解决办法就是把dom操作用ng- ...

