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来填充给定组件中的依赖。主要是如下几个:

System_CAPS_pubmethodCompose(CompositionBatch)

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

   
System_CAPS_pubmethodGetExportedValue<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.)

System_CAPS_pubmethodGetExportedValue<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.)

   
System_CAPS_pubmethodSatisfyImportsOnce(ComposablePart)

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

   

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

   
System_CAPS_pubmethodSystem_CAPS_staticComposeParts(CompositionContainer, Object[])

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

   
System_CAPS_pubmethodSystem_CAPS_staticCreatePart(Object)

Creates a composable part from the specified attributed object.

   
System_CAPS_pubmethodSystem_CAPS_staticSatisfyImportsOnce(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();
        }
    }

 

转载于:https://www.cnblogs.com/Code-life/p/7728307.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值