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();
}
}
最新文章
- 【.net深呼吸】WPF异步加载大批量图像
- js中json对象和字符串的转换
- 【循序渐进学Python】10.模块和包
- [BZOJ1618][Usaco2008 Nov]Buying Hay 购买干草
- C#调用WORD处理的实例代码(包含excel)
- Socket解决粘包问题1
- pygame安装
- 【索引】gtest学习笔记
- C# 如何获取当前应用程序的父目录
- [bzoj1223] [HNOI2002]Kathy函数
- Android使用HttpClient以Post、Get请求服务器发送数据的方式(普通和json)
- 安装虚拟机,磁盘选择厚置备延迟置零与厚置备置零和Thin Provision有什么区别
- 微信公众号开发C#系列-8、自定义菜单及菜单响应事件的处理
- Android程序员必知必会的网络通信传输层协议——UDP和TCP
- 2.26 js解决click失效问题
- git 先建立本地分支,再传给线上库
- react native环境搭建(含错误处理)
- WordPress主题开发实例:查询单篇文章
- Netty Message RefCount
- Java 设计模式之单利模式