在之前的教程中,介绍了MEF(Managed Extensibility Framework)的基本概念,并通过一个控制台应用程序和一个Silverlight应用程序展示了框架的基本用法。本文将进一步深入探讨MEF及其优势,并通过一个控制台应用程序来展示其背后的原理,希望能够帮助更好地理解并在未来的开发中应用MEF。
首先,建议阅读之前的文章《MEF与Silverlight入门指南(第一部分)》,这将为提供开发MEF应用程序所需的基础知识。本文将基于该部分内容进行演示。
本教程的目标是创建一个应用程序,并在需要时添加其功能,而无需更改实际的应用程序代码。最终,只需要将新的DLL插件到应用程序中,就可以添加新功能,而无需对原始代码进行任何修改。如果将来想要添加更多新功能,可以通过将新的DLL部署到客户端PC上,用户就可以访问它们,而无需升级应用程序。如果用户想要移除某个功能,他们可以简单地通过移除相应的DLL来实现,而不会降低原始应用程序的性能。
听起来很有趣吧?那么让通过一个示例应用程序来讨论每个要点,这将帮助更好地理解MEF的强大功能。请阅读完整文章并享受其中的内容。
首先,使用Visual Studio 2010创建一个针对框架版本4.0的控制台应用程序。将使用Visual C#代码格式来演示示例应用程序。如果不熟悉这一点,建议阅读完整文章以了解基础知识,一旦理解了MEF的需求和用途,将能够轻松地使用另一种语言进行操作。
创建控制台应用程序项目后,向解决方案中添加一个类库项目。为此,请右键单击解决方案,然后从上下文菜单中点击“添加”->“新建项目”。
在“添加新项目”对话框中,选择“类库”模板,并将项目命名为“PersonLibrary”。点击“确定”,让Visual Studio IDE为创建相应的项目。
项目创建后,在库项目中创建一个名为“IPerson”的空白接口。接口如下所示:
public interface IPerson
{
// 接口内容
}
创建空白接口的原因仅仅是为了本示例,以便区分MEF框架需要满足的类型。
首先,需要在控制台应用程序项目中添加两个程序集引用。一个是PersonLibrary项目引用,另一个是System.ComponentModel.Composition.dll引用。为此,请右键单击主应用程序项目,然后点击“添加引用”。找到这些程序集并将它们包含在项目中。
PersonLibrary DLL引用是必需的,以便使用IPerson接口,而System.ComponentModel.Composition DLL引用是必需的,以便使用MEF组合和导入部分。
现在打开控制台应用程序项目的Program.cs,并创建一个IPerson类型的属性,以便可以导入许多IPerson类型的合同。将ImportMany属性设置到属性上。以下是代码详情:
[ImportMany(typeof(IPerson))]
public IEnumerable<IPerson> Persons { get; set; }
在Program类中,添加一个名为CreateCompositionContainerFromDirectory()的方法,并创建一个指向应用程序根目录的DirectoryCatalog。然后,从目录创建CompositionContainer,并调用ComposeParts()以满足容器。现在进入Main()方法,并在创建程序类实例后调用CreateCompositionContainerFromDirectory()。代码如下:
static void Main(string[] args)
{
var program = new Program();
program.CreateCompositionContainerFromDirectory();
program.ComposeParts();
}
关于导入部分的讨论到此为止。现在需要创建合同并将其导出到MEF。为此,让在同一个解决方案中创建另一个类库项目。将新库项目命名为EmployeeLibrary。添加PersonLibrary项目的程序集引用,以便在新库中使用IPerson接口。同样添加System.ComponentModel.Composition程序集引用以导出合同。
设置项目后,是时候创建类了。让创建一个名为“Employee”的类,并继承IPerson接口。在构造函数中打印一条消息,以便在生成类的实例时,它将在控制台中打印该消息。将“Export”属性设置为IPerson类型的类。
[Export(typeof(IPerson))]
public class Employee : IPerson
{
public Employee()
{
Console.WriteLine("Employee created.");
}
}
类似于上面的库项目,在同一解决方案中创建另一个库项目,并将其命名为CustomerLibrary。添加项目“PersonLibrary”的程序集引用和System.ComponentModel.Composition,就像为EmployeeLibrary所做的那样。
设置项目后,只需在该项目中创建一个类似于“Employee”的类,但这里将类命名为“Customer”。在构造函数中放入一条不同的消息,以便在创建此类的实例时,它将在控制台中打印出来。
[Export(typeof(IPerson))]
public class Customer : IPerson
{
public Customer()
{
Console.WriteLine("Customer created.");
}
}
哇!编码部分结束了。现在是时候进行演示,展示想要实现的目标以及所取得的成果。构建整个解决方案,并确保没有错误,解决方案构建成功。
转到主应用程序的debug文件夹内的bin目录,即“HelloMEFDemo3”。在那里,将找到由编译器生成的“HelloMEFDemo3.exe”。这是刚刚开发的控制台应用程序。双击它以运行应用程序。
哇!这是一个空白应用程序!Employee或Customer类发生了什么?
别担心。运行了应用程序,但应用程序不知道Employee或Customer类。没有添加引用以自动导入MEF。那么该怎么办?需要将引用添加到主控制台应用程序,对吧?不,等等,不应该在那里添加引用。原因是:“应用程序不应该知道合同部分。以后,将能够在不编写任何代码的情况下自动包含它们。”
那么,该怎么办?首先关闭控制台应用程序。现在转到名为“EmployeeLibrary”的项目bin目录,并将库DLL复制到控制台应用程序输出目录。查看下面的屏幕截图。只是将EmployeeLibrary.dll放在可执行应用程序的根文件夹中。
现在,再次运行应用程序,将看到屏幕上打印的消息。
关闭控制台窗口,并将CustomerLibrary.dll从项目输出目录复制到应用程序根目录。再次运行控制台应用程序。将看到客户的消息也打印在屏幕上。请查看这里的输出:
通过这个小演示,学到的是:“无需更改实际应用程序,就可以非常容易地插入新代码”。在不更改主应用程序的情况下,很容易在应用程序中包含额外的功能。只需要将DLL库放到适当的位置,以便应用程序可以拾取。如果将来需要移除某些功能,只需要从用户目录中移除引用DLL。无需将应用程序回滚到以前的版本。
这对于实现额外功能并将其插入到客户端应用程序非常有用。同时,它也非常容易维护版本控制。因此,它为代码提供了更多的灵活性和可扩展性。
希望这能帮助更详细地理解MEF。现在可以想象它在应用程序开发中的强大功能。继续探索它吧。
不要忘记投票。建议和反馈总是受欢迎的。