65.9K
CodeProject 正在变化。 阅读更多。
Home

.NET 4.0 MEF FAQ (Socket, 插件和扩展)

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.92/5 (73投票s)

2010年9月1日

CPOL

7分钟阅读

viewsIcon

145624

downloadIcon

1908

.NET 4.0 MEF FAQ (Socket, 插件和扩展)

视频更新....

本视频介绍了.NET 4.0 的一个功能,称为 MEF(托管扩展性框架)。

目录

引言和目标

本 FAQ 深入探讨了 .NET 4.0 MEF 的基础知识(Import 和 Export),并解释了何时使用 MEF 而不是 DI/IOC。本文还逐步介绍了如何在 Silverlight、WPF 和 ASP.NET 等各种技术中使用 MEF。

请随时下载我免费的 .NET 电子书,其中包含 WCF、WPF、WWF、Silverlight 等 400 个问答,在此处下载。

什么是 MEF(托管扩展性框架)?

MEF 是一个可以使您的应用程序可扩展的框架。例如,您有一个会计应用程序,并且希望提供一个挂钩(socket),外部供应商可以连接(plug)到该挂钩并为会计应用程序添加发票功能。

例如,您有一个应用程序,希望不同的供应商通过自己的功能与之连接并扩展您的应用程序。

因此,供应商只需将组件放入应用程序中,应用程序就会发现它们并进行连接和扩展。

如何在 .NET 4.0 中实现 MEF?

实现 MEF 是一个三步过程:

• Import(创建 socket):使用“Import”属性在您的应用程序中定义一个挂钩或 socket。
• Export(连接插件):使用“Export”属性创建可以连接到插件或挂钩的插件。
• Compose(进行扩展):使用组合容器并进行组合。

能否结合以上三个步骤,看一个简单的 MEF 示例?

我们将创建一个简单的类,该类将有一个挂钩来导入 string 消息。换句话说,任何具有 string 消息实现功能的类都可以连接到该挂钩并扩展该类。

第一步:创建 Socket(Import)

第一步是创建一个占位符/挂钩/socket,其他组件可以插入其中。

导入 MEF 所需的以下命名空间。

using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Reflection;

为了定义一个挂钩,我们创建了一个名为“ImportMessage”的空属性,并为其添加了“Import”属性。

class Program
{
[Import()]
public string ImportMessage
{
set;
get;
}
}

上面的“import”属性表示任何拥有 string 功能实现类型的类都可以连接到我并附加该功能。

第二步:创建并连接插件(Export)

为了创建插件或扩展,我们需要使用如下所示的“Export”属性。在当前场景下,此属性不执行任何操作,只是显示一个简单的 string

class clsMySimpleMessage
{
[Export()]
string ExportMessage
{
set
{
}
get
{
return "Message inserted via MEF";
}
}
}

第三步:连接并扩展(Compose)

好的,我们已经创建了 socket 和插件,现在是时候将它们连接起来了。以下是相关的代码:

private void Compose()
{
// Get a reference to the current assemblies in the project.
AssemblyCatalog catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());

// Once you have got the reference of catalog add it to the composition container.
CompositionContainer compositionContainer = new CompositionContainer(catalog);

// Finally call composeparts to connect the Import with Export.
compositionContainer.ComposeParts(this);

// use the property
Console.WriteLine(ImportMessage);
Console.ReadLine();
}

换句话说,Export、Import 和 Compose。下图对此进行了总结。

Export”就像您提供的东西,而“import”就像您接收的东西。

Import 和 Export 的数据类型是否必须匹配?

Import 和 Export 的类型必须匹配,否则在组合时会收到如下所示的错误。不兼容的 socket 和插件能连接吗?

能否通过某个定义的契约而不是 .NET 数据类型来连接 Import 和 Export?

在现实世界中,您的挂钩应该是像客户、供应商等实际的契约类型,而不是像 stringintBoolean 等简单的 .NET 数据类型。为了在 MEF 中创建现实世界的挂钩,我们首先需要使用接口创建契约,如下所示:

interface ImyInterface
{
string getString();
}

我们需要确保 importexport 属性中定义的挂钩是相同的接口类型,如下所示。使用组合容器的绑定逻辑没有改变;与上一节的描述相同。

[Export(typeof(ImyInterface))]
class clsMyImplementation : ImyInterface
{
public string getString()
{
return "This is my string";
}
}
class Program
{
[Import()]
public ImyInterface myInterface
{
set;
get;
}
}

这看起来与 DI 和 IOC 非常相似,为什么还要重复发明?

如果您不熟悉 DI/IOC,请在此处阅读

它们在很大程度上是重叠的,但目标不同。DI 和 IOC 用于解耦,而 MEF 用于可扩展性。以下需求将更详细地说明如何选择解决方案:

要求 解决方案
应用程序应为分层应用程序,每个层都与其他层解耦,以实现更好的可重用性和可维护性。 DI IOC
应用程序应提供将数据导出为不同格式的功能。外部供应商应能够插入自己的导出机制到应用程序中。 MEF

下表对此进行了详细总结:

  DI / IOC MEF
解耦  
可扩展性  
集成已知项  
集成未知项  
自动发现  
注册  
发现  
编译时  
运行时  

如果您仍有疑问,请在此处联系 Glenn Block

它们可以协同工作吗?

假设您有一个应用程序,并且有以下需求:

 

要求 解决方案
应用程序应为三层架构,UI、BO 和 DAL 层彼此解耦。 DI IOC
数据访问层需要开放且可扩展。应用程序将允许供应商插入自己的数据连接机制,以便应用程序可以连接到他们的专有数据库。 MEF

处理第一个需求的方法是使用您喜欢的 IOC 容器,而第二个需求就是 MEF 发挥作用的地方。下图展示了它们如何在整个体系中发挥作用。

在两者之间做出选择时,最终目标更为重要。

尼古拉斯·布鲁姆哈特(Mr. Nicholas Blumhardt)的这篇精彩文章展示了 MEF 和 IOC 如何协同工作。

我们想看一个 Silverlight 的示例?

主要重要步骤不变。

第一步:创建 Socket(Import)

定义您想要导入的 Silverlight 项。在下面的代码片段中,我们定义了一个用户控件类型的集合。

public partial class MainPage : UserControl
{
[ImportMany]
public ObservableCollection<UserControl> ImportedItems
{ get; set; }
}

第二步:创建并连接插件(Export)

使用“Export”来定义插件。对于当前场景,我们定义了两个 Silverlight 用户控件,并使用 export 属性公开“UserControl”作为类型。

[Export(typeof(UserControl))]
public partial class SilverlightControl1 : UserControl
{
public SilverlightControl1()
{
InitializeComponent();
}
}


[Export(typeof(UserControl))]
public partial class SilverlightControl2 : UserControl
{
public SilverlightControl2()
{
InitializeComponent();
}
}

第三步:连接并扩展(Compose)

使用“SatisfyImport”来组合 exports 和 imports。

CompositionInitializer.SatisfyImports(this);

如果运行它,您应该会在主 Silverlight UI 容器中看到组合的用户控件,如下所示:

整个 Silverlight 的图景如下所示:

能否也看一个 WPF 的简单示例?

呼……累了,稍后更新。

ASP.NET 的示例怎么样?

呼……累了,稍后更新。

源代码

您可以从本文顶部的链接下载源代码。

参考

如需进一步阅读,请观看以下面试准备视频和分步视频系列。

© . All rights reserved.