MEF初体验之七:Using Catalogs

MEF特性化编程模型的价值主张之一是通过catalogs动态发现部件的能力。Catalogs允许应用程序很容易地消费那些通过[Export]已经自我注册的exports。

Assembly Catalog

为了在一个特定的程序集中发现所有的exports,可以使用System.ComponentModel.Composition.Hosting.AssemblyCatalog类。

var catalog = new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly());

Directory Catalog

为了在一个目录中所有程序集中发现所有的exports,可以使用System.ComponentModel.Composition.Hosting.DirectoryCatalog类。

var catalog = new DirectoryCatalog("Extensions");

如果使用的是一个相对的目录,它将相对于当前AppDomain的基本目录。

DirectoryCatalog将扫描这个目录一次,当这个目录发生变化时,它将并不会自动刷新。然而,你可以实现你自己的扫描机制,在catalog上调用Refresh()方法使它重新扫描。一旦它重新扫描,将发生重组。

var catalog = new DirectoryCatalog("Extensions");
//some scanning logic
catalog.Refresh();

注意:在sliverlight中不支持DirectoryCatalog。

Aggregate Catalog

当AssemblyCatalog and DirectoryCatalog单独不充足,需要结合的catalogs时,应用程序可以使用System.ComponentModel.Composition.Hosting.AggregateCatalog类。一个AggregateCatalog将多个catalogs组合到一个单一的catalog中。通用的模式是添加当前执行的程序集和第三方扩展的一个directory catalog。你可以将要组合的catalog作为AggregateCatalog构造器参数或者使用AggregateCatalog的Catalogs属性来直接添加。

var catalog = new AggregateCatalog(
  new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly()), 
  new DirectoryCatalog("Extensions"));

Type Catalog

为了在一系列指定的类型中发现所有的导出,将可以使用System.ComponentModel.Composition.Hosting.TypeCatalog类。

var catalog = new TypeCatalog(typeof(type1), typeof(type2), ...);

DeploymentCatalog - Sliverlight only

在Sliverlight中,MEF包含DeploymentCatalog,用来动态下载远程XAPs。有关更多DeploymentCatalog内容请查看DeploymentCatalog

Using catalog with a Container

为了使用catalog和container,只需简单地将catalog传到container的构造器即可。

var container = new CompositionContainer(catalog);

最后举个例子:

首先,在CommonLib类库中定义了一个接口:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CommonLib
{
    public interface ILogger
    {
        void Log(string msg);
    }
}

然后,创建CatalogLib类库,引用CommonLib类库,并在里面定义一个ILogger类型契约的exports:

using CommonLib;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CatalogLib
{
    [Export(typeof(ILogger))]
    public class FileLogger:ILogger
    {
        public void Log(string msg)
        {
            Console.WriteLine("File Logger:"+msg);
        }
    }
}

最后,创建CatalogsSample控制台程序,将CatalogLib的生成路径也改为该生成路径,并引用CommonLib,也创建一个ILogger类型契约的exports,在入口处组合,代码如下:

using CommonLib;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace CatalogsSample
{
    class Program
    {
        [ImportMany]
        public IEnumerable<ILogger> Loggers { get; set; }
        static void Main(string[] args)
        {
            Program p = new Program();
            p.Compose();
            foreach (var item in p.Loggers)
            {
                item.Log("Hi,MEF");
            }
            Console.ReadKey();
        }
        void Compose()
        {
            var catalog = new AggregateCatalog(new AssemblyCatalog(Assembly.GetExecutingAssembly()), new DirectoryCatalog("."));
            var container = new CompositionContainer(catalog);
            container.ComposeParts(this);
        }
    }
    [Export(typeof(ILogger))]
    class DBLogger : ILogger
    {
        public void Log(string msg)
        {
            Console.WriteLine("DB Logger:" + msg);
        }
    }
} 

输出如图:

原文地址:https://www.cnblogs.com/jellochen/p/3663054.html