MEF框架学习之旅(三)组合

1、框架中的Catalog

在MEF框架中,包含了4种Catalog,所有的Catalog的是从System.ComponentModel.Composition.Primitives名称空间下的ComposablePartCatalog抽象类派生下来。

 

AssemblyCatalog:表示从程序集中搜索部件的目录。

DirectoryCatalog:表示从文件系统的指定路径中,搜索程序集,从而搜索部件。

TypeCatalog:表示从指定的类型集合中,去搜索相应的部件。

AggregateCatalog:聚合目录,可以添加上面所说的所有目录,从而进行多方面的部件搜索。

直接添加部件到容器:

 在CompositionContainer类里里通过重载方法ComposeParts()手动添加每个组成部件。下面的例子里一个LoggerProxy的实例和当前要导入的Program实例一起添加到容器

代码段

   container.ComposeParts(this, new LoggerProxy());

 

 

2、自定义Catalog

自定义Catalog和系统实现的Catalog类似,我们通过继承System.ComponentModel.Composition.Primitives空间下的ComposablePartCatalog类,并且覆写掉基类的方法即可。

 要实现自己的Catalog,必须要覆写掉Parts属性,如有特别需要处理的,我们还可以覆写GetExports方法,此方法默认的调用了Parts属性,进行进一步的输出。

例如实现目录过滤筛选功能:

在使用MEF目录进行导出部件托管的时候,在某些需求下或许只需要其中的一个部件,这种情况可以通过遍历部件集合得到。然而MEF也为此提供了一种解决方案,那就是使用目录过滤筛选功能。MEF中的ComposablePartCatalog类和INotifyComposablePartCatalogChanged接口就是专门用来实现目录筛选的,可以如下代码段中演示的对目录过滤的封装。

代码段

        public class FilteredCatalog : ComposablePartCatalog, INotifyComposablePartCatalogChanged
        {
            private readonly ComposablePartCatalog _inner;
            private readonly INotifyComposablePartCatalogChanged _innerNotifyChange;
            private readonly IQueryable<ComposablePartDefinition> _partsQuery;


            public FilteredCatalog(ComposablePartCatalog inner,
                                Expression<Func<ComposablePartDefinition, bool>> expression)

            {
                _inner = inner;

                _innerNotifyChange = inner as INotifyComposablePartCatalogChanged;

               _partsQuery = inner.Parts.Where(expression);

            }


            public event EventHandler<ComposablePartCatalogChangeEventArgs> Changed
            {

                add
                {
                    if (_innerNotifyChange != null)
                        _innerNotifyChange.Changed += value;

                }
                remove
                {
                    if (_innerNotifyChange != null)

                       _innerNotifyChange.Changed -= value;
                }
             }


            public event EventHandler<ComposablePartCatalogChangeEventArgs> Changing
            {
                add
                {
                    if (_innerNotifyChange != null)
                        _innerNotifyChange.Changing += value;
                }
                remove
                {

                    if (_innerNotifyChange != null)

                        _innerNotifyChange.Changing -= value;
                }

            }
            public override System.Linq.IQueryable<ComposablePartDefinition> Parts
            {

                get
                {
                    return _partsQuery;
                }
            }
        }

 

 

3、综合示例

解决方案如下:

 

其中MEFParts为一个类库项目,并且生成输出路径是在MyConsoleMEF输出路径下的Parts目录中。

Program中,我们输出了所有的Part,代码如下:

代码段

   class Program
    {
        private static CompositionContainer container;

        [ImportMany]
        public ILogger[] Loggers { get; private set; }

        static void Main(string[] args)
        {

            Program p = new Program();


            //AssemblyCatalog:表示从程序集中搜索部件的目录
            var assemblyCatalog = new AssemblyCatalog(typeof(Program).Assembly);
            //相当于var assemblyCatalog = new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly());
            //DirectoryCatalog:表示从文件系统的指定路径中,搜索程序集,从而搜索部件
            var directoryCatalog = new DirectoryCatalog(AppDomain.CurrentDomain.BaseDirectory + "\\Parts", "*.dll");
            //TypeCatalog:表示从指定的类型集合中,去搜索相应的部件
           var typeCatalog = new TypeCatalog(typeof(ConsoleLogger));
            //AggregateCatalog:聚合目录,可以添加上面所说的所有目录,从而进行多方面的部件搜索
            var aggregateCatalog = new AggregateCatalog(assemblyCatalog, directoryCatalog, typeCatalog);

            container = new CompositionContainer(aggregateCatalog);

            var exports = container.GetExports<ILogger>();
            foreach (var exportValue in exports)
            {

                Console.WriteLine(exportValue.Value.GetType());

            }
             Console.Read();
        }
   }

 

相关阅读:

MEF框架学习之旅(十一)调试

MEF框架学习之旅(十)重组

MEF框架学习之旅(九)部件生命周期及组装通知

MEF框架学习之旅(八)避免发现

MEF框架学习之旅(七)部件的创建规则(策略)

MEF框架学习之旅(六)元数据和元数据视图

MEF框架学习之旅(五)导入导出(下)

MEF框架学习之旅(四)导入导出(上)

MEF框架学习之旅(三)组合

MEF框架学习之旅(二)契约

MEF框架学习之旅(一)概念

posted @ 2013-06-01 22:03  一个人在北京  阅读(3951)  评论(3编辑  收藏  举报