声明导出
组成部件通过[System.ComponentModel.Composition.ExportAttribute]特性声明导出。在MEF有几种不同方法去声明导出,包括部件级别和通过属性和方法。
组成部件导出
当一个部件需要导出自身时一个组成部件级别的导出经常用。为了让部件导出自己,简单的方法是用[System.ComponentModel.Composition.ExportAttribute]特性修饰一个组成部件,正如下面所示一样:
[Export] public class SomeComposablePart { ... }
属性导出
部件也可以导出属性。属性导出有下面几个优点:
- 他们允许导出密封类型例如核心CLR类型,或者其它第三方类型。
- 他们允许从怎样创建导出中解耦导出。例如导出运行环境为你创建的现有的HttpContext。
- 他们允许有导出同一个组成部件关系的成员,例如一个DefaultSendersRegistry组成部件导出一个sender默认设置作为属性。
举例你有一个Configuration类要导出一个整形”Timeout"契约,正如下面代码一样:
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; } }
方法导出
方法导出是部件导出它的一个方法。方法被作为委托导出,它在导出契约中被指定。方法导出有下面几个好处:
- 他们允许好的细致控件作为导出。例如,一个规则引擎要导入一个插入式设置的方法导出。
- 他们从任务知识的类型串保护调用者。
- 他们可以通过轻量的代码情报中产生,你不能用其它导出做得到。
注意:由于framework的局限性,方法导出不可以超过4参数。
在下面的例子里,MessageSender类导出它的Send方法作为Action<string>委托。Processor导入相同的委托。
public class MessageSender { [Export(typeof(Action<string>))] public void Send(string message) { Console.WriteLine(message); } } [Export] public class Processor { [Import(typeof(Action<string>))] public Action<string> MessageSender { get; set; } public void Send() { MessageSender("Processed"); } }
你也可以通过使用一个简单的字符串契约导出和导入方法。例如下面所用的“Sender"契约
public class MessageSender { [Export("MessageSender")] public void Send(string message) { Console.WriteLine(message); } } [Export] public class Processor { [Import("MessageSender")] public Action<string> MessageSender { get; set; } public void Send() { MessageSender("Processed"); } }
注意:当用方法导出时,你需要提供一个类型或者一个字符串契约名,并且不能留空。
继承导出
MEF支持基类/基接口去定义导出的功能,这样它就可以被继承。这是综合遗产框架的目标,它利用MEF去发现但不需要修改现存的自定义代码。为了提供这个功能,使用System.ComponentModel.Composition.InheritedExportAttribute.例如下面的ILogger有一个InheritedExport。Logger继承ILogger所以它自动导出ILogger。
[InheritedExport] public interface ILogger { void Log(string message); } public class Logger : ILogger { public void Log(string message); }
发现非公共的组成部件
MEF支持发现公共和非公共的部件。你不需要去做任何事就能实现这个行为。请注意在中间/部份信任环境(包括Silverlight)非公有组成不被支持。