在""中,客户端应用程序调用了所有的扩展组件,而且如果有新的扩展组件加入,必须先关闭程序,再重新启动才可以调用所有组件。
本篇体验使用MEF的ExportMetadata特性,有选择性地使用某些扩展组件,使用Lazy<>,让客户端程序延迟动态加载组件,即使不关闭应用程序,也能调用所有组件。
● StudentMEF.Lib, 类库,包含接口IStudent.cs
● StudentMEF.One,类库,包含实现IStudent的类One.cs ● StudentMEF.Two,类库,包含实现IStudent的类One.cs ● StudentMEF.Client,控制台程序
□ 所有扩展满足的约定是
namespace StudentMEF.Lib
{ public interface IStudent { string GetName(); int GetScore(); } }
□ StudentMEF.One类库
→ 需引用StudentMEF.Lib组件
→ 需引用System.ComponentModel.Composition组件
using System.ComponentModel.Composition;
using StudentMEF.Lib;namespace StudentMEF.One
{ [Export(typeof(IStudent))] [ExportMetadata("Type","ONE")] public class One : IStudent { private string _Name; private int _Score;public One()
{ _Name = "jack"; _Score = 80; } public string GetName() { return _Name; }public int GetScore()
{ return _Score; } } }
□ StudentMEF.Two类库
→ 需引用StudentMEF.Lib组件
→ 需引用System.ComponentModel.Composition组件
using System.ComponentModel.Composition;
using StudentMEF.Lib;namespace StudentMEF.Two
{ [Export(typeof(IStudent))] [ExportMetadata("Type","TWO")] public class Two : IStudent { private string _Name; private int _Score;public Two()
{ _Name = "Bob"; _Score = 90; }public string GetName()
{ return _Name; }public int GetScore()
{ return _Score; } } }
□ StudentMEF.Client控制台程序
→ 需引用StudentMEF.Lib组件
→ 需引用System.ComponentModel.Composition组件 → 需在可执行程序所在目录,即生成路径下,创建Extensions文件夹
需要一个帮助类StudentFactory,他的职责包括:
1、为了动态加载Extensions文件夹的所有扩展组件,可以使用Lazy<>来动态实现延迟加载,即只有当客户端程序使用到Extensions文件夹中组件的时候,再去加载这些扩展组件。
2、把扩展组件放到Catalog中,在CompositionContainer构建Part等,这些常规操作,也都需要。 3、提供一个方法,根据元数据ExportMetadata来获取对应的组件。
using System;
using System.Collections.Generic; using System.ComponentModel.Composition; using System.ComponentModel.Composition.Hosting; using StudentMEF.Lib;namespace StudentMEF.Client
{ public class StudentFactory { [ImportMany] private Lazy<IStudent, IDictionary<string, object>>[] Students { get; set; }public StudentFactory()
{ var catalog = new AggregateCatalog(); catalog.Catalogs.Add(new DirectoryCatalog(@".\Extensions")); var container = new CompositionContainer(catalog); container.ComposeParts(this); }public List<IStudent> GetStudents(string c)
{ List<IStudent> result = new List<IStudent>(); foreach (var student in Students) { if ((string)student.Metadata["Type"] == c) { result.Add(student.Value); } } return result; } } }Lazy<IStudent, IDictionary<string, object>>中,第二个参数IDictionary<string, object>与ExportMetadata("Type","TWO")对应。
static void Main(string[] args)
{ string c = ""; while (true) { Console.WriteLine("输入学生类型:"); c = Console.ReadLine(); StudentFactory studentFactory = new StudentFactory(); List<IStudent> students = studentFactory.GetStudents(c.ToUpper()); if (students.Count == 0) { Console.WriteLine("没有此类型学生~"); } else { foreach (IStudent student in students) { Console.WriteLine(string.Format("姓名:{0},分数:{1}",student.GetName(),student.GetScore())); } } } Console.ReadKey(); }
当Extensions文件夹中只有StudentMEF.One.dll组件,输入one,找到匹配,输入two找不到匹配;不关闭控制台程序,把StudentMEF.Two.dll也放入 Extensions文件夹,再输入two,找到匹配。