MEF体验使用接口导出的优越性
组合部件是MEF的组合单元,一个组合部件可以为其他部件提供导出服务,也可以导入其他部件的服务,一个部件至少包含一个导出。在MEF中通过Export和Import特性来标示导出和导入,部件可以直接添加到组合容器,也可以通过目录添加到组合容器,默认的目录是通过Export来标示的。
部件之间没有依赖关系,但是部件都依赖于契约。默认情况下应使用类型契约而不是字符串契约,字符串契约容易导致模糊。如果必须使用可以添加公司名称、命名空间等前缀。
对于导出的契约可以使用固定的类,但是通常使用接口和抽象类,这样用很方便一次导入多个不同的类,下面通过示例来展示这个优越性。
注:这样使用必须每个导出标记特定的接口类型否则类型本身被导出
示例:
using System; using System.ComponentModel.Composition; using System.ComponentModel.Composition.Hosting; using System.Collections.Generic; namespace ContractConsole { /// <summary> /// 宿主 /// </summary> class Program { /// <summary> /// 导入特定的导出集 /// </summary> [ImportMany] public IEnumerable<IWaiter> waiters { get; set; } static void Main(string[] args) { Program p = new Program(); p.Run(); } /// <summary> /// 测试导入 /// </summary> public void Run() { Compent(); Notify("小张"); Console.Read(); } /// <summary> /// 组合容器 /// </summary> private void Compent() { var catalog = new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly()); var container = new CompositionContainer(catalog); container.ComposeParts(this); } /// <summary> /// 调用导入对象的方法 /// </summary> /// <param name="name"></param> public void Notify(string name) { foreach (IWaiter waiter in waiters) { waiter.Hellow(); waiter.Service(name); waiter.GoodBye(); Console.WriteLine(); } } } /// <summary> /// 接口 /// </summary> public interface IWaiter { void Hellow(); void Service(string name); void GoodBye(); } /// <summary> /// 导出餐厅类 /// </summary> [Export(typeof(IWaiter))] public class DiningRoomWaiter : IWaiter { public void Hellow() { Console.WriteLine("欢迎光临老麻抄手!"); } public void Service(string name) { Console.WriteLine("先生您要的三两清汤抄手,请慢用!-----------" + name); } public void GoodBye() { Console.WriteLine("欢迎下次光临!"); } } /// <summary> /// 导出酒吧类 /// </summary> [Export(typeof(IWaiter))] public class BarWaiter : IWaiter { public void Hellow() { Console.WriteLine("欢迎光临炫酷酒吧!"); } public void Service(string name) { Console.WriteLine("先生您要的一杯啤酒,请慢用!-----------" + name); } public void GoodBye() { Console.WriteLine("欢迎下次光临!"); } } }
执行结果: