在"MEF(Managed Extensibility Framework)使用全部扩展组件"中,客户端应用程序调用了所有的扩展组件,而且如果有新的扩展组件加入,必须先关闭程序,再重新启动才可以调用所有组件。
本篇体验使用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,找到匹配。