MEF初体验之二:定义组合部件和契约
2014-04-12 15:27
525 查看
组合部件
在MEF中,一个组合部件就是一个组合单元,组合部件"出口"其它组合部件需要的服务并且从其它部件"进口"需要的服务。在MEF编程模型中,为了声明组合部件的"出口"和"进口",使用的是ExportAttribute和ImportAttribute。一个组合部件至少应该包含一个[Export]。组合部件既可以被显式的添加到Container,也可以通过使用Catalogs来创建。MEF附带的默认的Catalogs是通过[Export]来识别组合部件的。契约
组合部件并不直接依赖另一个组合部件,而是依赖一个由字符串标识的契约。每一个[Export]都有一个契约,每一个[Import]都声明了它需要的契约。Container使用契约来Import部件匹配Export组件。如果未指定契约,MEF将隐式地将类型的全限定名作为契约。如果被传递的是一个类型,也将采用上面的方式。注意:默认是传递一个type而不是一个字符串。尽管契约可以是任意的字符串,但是这可能会导致歧义。例如,一个名为"Sender"的契约可能会和另一个类库的名为"Sender"的契约重叠。处于这样的原因,如果你需要指定一个字符串契约,建议使用包含公司名称的命名空间来限定,例如 "Contoso.Exports.Sender"。
在下面的code snippet中,所有的export契约都是等价的。
[Export] class Exporter { } [Export(typeof(Exporter))] class Exporter1 { } [Export("PartsAndContracts.Exporter")] class Exporter2 { }
接口/抽象契约
一个通用的模式是为一个组合部件export一个接口或者一个抽象类型的契约而不是一个具体的类型。这允许import组件完全不耦合于将要import的export组件的具体实现,从而导致关注点的分离。例如,下面你可以看到有两个都export了IMessageSender接口的Sender实现。这个Notifier类import一个IMessageSender类型的集合,我们调用分别调用每一个的Send()方法。现在一个的message senders可以很容易地被添加到系统中。using System; using System.Collections.Generic; using System.ComponentModel.Composition; using System.ComponentModel.Composition.Hosting; using System.Linq; using System.Text; using System.Threading.Tasks; namespace PartsAndContracts { class Program { static void Main(string[] args) { Program p = new Program(); Notifier noter = new Notifier(); var container = new CompositionContainer(); container.ComposeParts(noter, new EmailSender(), new TcpSender(),new PhoneSender()); noter.Notify("Hi,MEF"); Console.WriteLine("-----------------"); noter.MessageSender.Send("Hi,MEF"); Console.ReadKey(); } } class Notifier { [ImportMany] public IEnumerable<IMessageSender> Senders { get; set; } [Import("PhoneSender")] public IMessageSender MessageSender { get; set; } public void Notify(string msg) { foreach (var item in Senders) { item.Send(msg); } } } interface IMessageSender { void Send(string msg); } [Export(typeof(IMessageSender))] class EmailSender : IMessageSender { public void Send(string msg) { Console.WriteLine("Email Sent:"+msg); } } [Export(typeof(IMessageSender))] class TcpSender : IMessageSender { public void Send(string msg) { Console.WriteLine("TCP Sent:"+msg); } } [Export("PhoneSender",typeof(IMessageSender))] class PhoneSender : IMessageSender { public void Send(string msg) { Console.WriteLine("Phone Sent:" + msg); } } }
如图显示:
在上面例子中,组合部件通过type契约使得export的EmailSender和TcpSender实例import到Senders属性,通过string identifier契约使得PhoneSender部件和MessageSender匹配。
相关文章推荐
- MEF 编程指南(二):定义可组合部件和契约
- [MEF程序设计指南]定义可以组合的部件和契约
- MEF程序设计指南三:MEF中组合部件(Composable Parts)与契约(Contracts)的基本应用
- 【转】MEF程序设计指南三:MEF中组合部件(Composable Parts)与契约(Contracts)的基本应用
- 【转】MEF程序设计指南三:MEF中组合部件(Composable Parts)与契约(Contracts)的基本应用
- MEF程序设计指南三:MEF中组合部件(Composable Parts)与契约(Contracts)的基本应用
- MEF中组合部件(Composable Parts)与契约(Contracts)的基本应用 推荐
- MEF程序设计指南三:MEF中组合部件(Composable Parts)与契约(Contracts)的基本应用
- MEF系列二:定义部件(Parts)和契约(Contracts)
- MEF程序设计指南三:MEF中组合部件(Composable Parts)与契约(Contracts)的基本应用
- MEF学习笔记(2):定义组成部件和契约
- MEF初体验之十一:查询组合容器
- MEF初体验之十:部件重组
- 抓虫记之二:WSDL中消失的函数定义
- 组合、继承和代理三者的定义
- 产品框架初步设计后,如何为每个部件定义一个清晰的职责范畴?
- MEF程序设计指南五:迟延(Lazy)加载导出部件(Export Part)与元数据(Metadata)
- MEF: MSDN 杂志上的文章(15) 拒绝【多个导出,但只用一个导入,会拒绝,但还是稳定的组合】
- Unity 5.x BuildAssetBundles 角色换装 加载ab包 资源管理 根据部件组合完整角色
- COCOS2D-HTML5 开发之二】cocos2d-html5项目定义成员,局部变量,函数笔记随笔