组合部件声明导出通过
[System.ComponentModel.Composition.ExportAttribute]属性。在MEF中有几种不同的方法通过属性和方法去声明导出包括部件级别
组合部件导出
组合部件级别导出用于
当组合部件需要导出它本身时,为了组合部件导出它本身,简单用[System.ComponentModel.Composition.ExportAttribute] 修饰组合部件如下面的代码片断
[Export] public class SomeComposablePart { ... }
属性导出
部件还可以导出属性,几个原因说明属性导出是有益的
- 它们允许导出封闭类型如CLR核心类型,或者其它第三方部件类型
- 它们允许解耦部件跟部件之间的创建,例如导出运行时创建的HttpContext
- 它们允许在相同的家庭相关的导出组合部分,如DefaultSendersRegistry可组合部分导出一个默认设置senders的属性
例如在下面的例子中你可能拥有一个导出integer对象,契约为"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; } }
方法导出
方法导出就是对象其中的一个方法导出。
Methods are exported as delegates which are specified in the Export contract. 方法导出包括以下几个好处
- 导出允许更细颗粒度控制,例如,规则引擎可以导入一套插入式方法导出。
- 避免了调用者对类型的任何认识
- They can be generated through light code gen, which you cannot do with the other exports.
注:方法导出可能没有超过4参数由于框架的限制
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
[InheritedExport] public interface ILogger { void Log(string message); } public class Logger : ILogger { public void Log(string message); }
发现非公共组合部件
MEF支持发现公共和非公共部件。这种行为不需要你做任何事,请注意在媒介和部分信任环境(包括Silverlight)非公共部分将不支持。
using System.ComponentModel.Composition; using System.ComponentModel.Composition.Hosting; using System.Reflection; using System; public class Program { public static void Main(string[] args) { Program p = new Program(); p.Run(); } public CompositionContainer container = null; /// <summary> /// Set the container global variable /// </summary> private void Compose() { AssemblyCatalog catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly()); container = new CompositionContainer(catalog); } public void Run() { Compose(); // Calling a method without use interfaces. More flexible and "easy to use". // Useful for plugins foreach (var view in container.GetExports<Func<string, bool>>("MessageSender")) { Console.WriteLine(view.Value("PUC-Campinas")); } Console.ReadKey(); } } public class MessageSender { [Export("MessageSender")] public bool Send(string message) { Console.WriteLine(message); return true; } }
注:以上只是为了方便我自己学习记录,有些地方翻译不到位,唯恐误导读者,如有需要请阅读原文
http://mef.codeplex.com/wikipage?title=Declaring%20Exports&referringTitle=Guide