组合部件通过[ExportAttribute]声明exports。在MEF中,有这么几种成员可声明exports的方式:组合部件(类)、字段、属性和方法。我们来看下ExportAttribute类的声明:
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Method
| AttributeTargets.Class, AllowMultiple=true, Inherited=false)] public class ExportAttribute : Attribute { }
果然,支持这四种成员,另外,在同一个目标上可应用多次该特性但是它不支持继承,如果想继承则需使用ExportAttribute的派生类InheritedExportAttribute来实现。
组合部件导出被用在当需要导出它自己的时候。在前面的例子中,我们使用的都是这种方式。
[Export(typeof(IMessageSender))] class EmailSender : IMessageSender { public void Send(string msg) { Console.WriteLine("Email Sent:"+msg); } }
这里,我们需要将EmailSender部件自身导出,其实就是类级别的导出。
组合部件也可以导出属性。属性导出有这么几个优点:
using System; using System.Collections.Generic; using System.ComponentModel.Composition; using System.Configuration; using System.Linq; using System.Text; using System.Threading.Tasks; using System.ComponentModel.Composition.Hosting; namespace ExportsDeclaring { class Program { [Import] public UsesTimeout UsesTimeout { get; set; } static void Main(string[] args) { Program p = new Program(); p.Compose(); Console.WriteLine(p.UsesTimeout.Timeout); Console.ReadKey(); } void Compose() { var container = new CompositionContainer(); container.ComposeParts(this, new UsesTimeout(),new Configuration()); } } public class Configuration { [Export("Timeout")] public int Timeout { get { return int.Parse(ConfigurationManager.AppSettings["Timeout"]); } } } [Export] public class UsesTimeout { [Import("Timeout")] public int Timeout { get; set; } } }
在上面的代码之前,需要先在配置文件中配置key为Timeout的AppSetting,例如:<add key="Timeout" value="5000"/>。
输出为:
方法导出是用在一个部件要将它的方法导出的地方。通过在导出契约中指定委托的方式来导出方法。方法导出有下面的几点好处:
注意:由于框架的限制,方法导出最多不能超过四个参数。
在下面的例子中,MessageSender类将它的Send方法导出为一个Action<string>委托,这个Processor导入了这个相同的委托。
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 ExportsDeclaring { class Example { [Import] public Processor Processor { get; set; } static void Main() { Example e = new Example(); e.Compose(); e.Processor.Send(); Console.ReadKey(); } void Compose() { var container = new CompositionContainer(); container.ComposeParts(this, new Processor(), new MessageSender()); } } public class MessageSender { [Export(typeof(Action<string>))] public void Send(string msg) { Console.WriteLine(msg); } } [Export] public class Processor { [Import(typeof(Action<string>))] public Action<string> MessageSender { get; set; } public void Send() { MessageSender("Processed"); } } }
输出为:
你也可以使用一个简单的字符串契约来导入导出。但是,当进行方法导出时,你必须得提供一个类型或者字符串七月名称,而不能留空。
MEF支持在一个基类或者接口中定义的导出将自动地被它的实现类继承的能力。这对于与那些想要利用MEF来发现而不是要求修改已有的客户代码的传统框架来说是很理想的。为了提供这种能力需要使用[System.ComponentModel.Composition.InheritedExportAttribute]。例如下面的ILogger接口有一个[InheritedExport],Logger实现了该接口,因此自动地导出了ILogger。
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 ExportsDeclaring { class Example1 { [Import] public ILogger Logger { get; set; } static void Main() { Example1 e = new Example1(); e.Compose(); e.Logger.Log("Logging"); Console.ReadKey(); } void Compose() { var container = new CompositionContainer(); container.ComposeParts(this, new Logger()); } } [InheritedExport] public interface ILogger { void Log(string msg); } public class Logger : ILogger { public void Log(string msg) { Console.WriteLine(msg); } } }
MEF支持公有和非公有部件的发现。你不需要做任何事情来启用该行为。请注意:在并不完全受信任的环境中(包括sliverlight),非公有的组合将不被支持。
MEF初体验之三:Exports声明,布布扣,bubuko.com
原文:http://www.cnblogs.com/jellochen/p/3661576.html