MEF 编程指南(二):定义可组合部件和契约

可组合部件(Composable Parts)
 
在 MEF 内部可组合部件是一个可组合单元。可组合部件导出其他可组合部件需要的服务,并且从其他可组合部件导入服务。在 MEF 编程模型中,可组合部件用 [System.ComponentModel.Composition.Import] 和 [System.ComponentModel.Composition.Export] 特性标识,以便声明导出点和导入点。可组合部件应该包含至少一个导出点。可组合部件要么显式添加到容器或者通过使用目录创建。MEF 访问默认目录识别 Export 特性标识的可组合部件。
 
 
契约(Contacts)
 
可组合部件不直接依赖另一个,相反依赖字符串标识的契约。每个导出点享有一个契约,并且每个导入点申明的他所需的契约。容器利用契约信息在导入点和导出点之间做匹配。如果没有指定契约,MEF 会隐式使用完全限定名的契约类型。如果传递了类型,也会使用完全限定名。
 
注意:默认情况下通过类型传递给契约。尽管契约可以是任意字符串,但是可能导致歧义(Ambiguity)。比如:“Sender”可能与另一个库的“Sender”实现重叠。基于这个原因,如果需要指定字符串的契约,强烈建议契约名应该包括公司名的限定命名空间,例如:“Contoso.Exports.Sender”。
 
以下代码片段,所有导出契约是等价的(Equivalent)。
 
    [Export]
    public class Exporter { }
 
    [Export(typeof(Exporter))]
    public class Exporter1 { }
 
    [Export("Chapter02.Exporter")]
    public class Exporter2 { }

 

接口/抽象契约

针对可组合部件的一种常见模式是导出接口或者抽象类型,而不是一个具体的类型。这允许导入者完全从特定的导出实现中解耦,这导致关注点的分离。例如:下面可以看到两种导出 IMessageSender 的 Sender 实现。Notifier 类导入 IMessageSender 集合,调用他的 Send() 方法。新的 MessageSender 可以很容易添加到系统。
 
 
    [Export(typeof(IMessageSender))]
    public class EmailSender : IMessageSender
    {
        public void Send(string message)
        {
            Console.WriteLine("Invoke EmailSender Send() method");
            Console.WriteLine(message);
        }
    }
 
    [Export(typeof(IMessageSender))]
    public class TCPSender : IMessageSender
    {
        void IMessageSender.Send(string message)
        {
            Console.WriteLine("Invoke TCPSender Send() method");
            Console.WriteLine(message);
        }
    }
 
    public interface IMessageSender
    {
        void Send(string message);
    }

 

 
契约程序集(Contract Assemblies)
 
使用 MEF 构建可扩展应用程序时的常见模式是发布契约程序集。契约程序集仅包含使用者可以扩展应用程序的契约类型。通常是接口,但是也可能是抽象类。另外,契约程序集包含导入点使用的元数据(Metadata)视图接口,以及任何自定义 MEF 导出特性。

 
注意:你必须指定特定的存在的导出接口类型(IMessageSender),否则类型(EmailSender)本身将被导出。
 
原文地址:
posted @ 2014-04-16 23:50  安布雷拉  阅读(1087)  评论(1编辑  收藏  举报