MEF学习总结---Container层

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MEF学习总结---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学习总结---Container层的主要内容,如果未能解决你的问题,请参考以下文章

MEF学习总结---Primitive层

MEF学习总结---Attribute Model Programing

C#]插件编程框架 MAF 开发总结

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

使用 MEF 构建具有 n 层松散耦合的 MVC ASP.NET 应用程序

MEF:“可组合部件应包含至少一个导出”