高级MEF编程






3.80/5 (5投票s)
高级MEF编程
导入类型
.NET 4.0 引入了许多新的编程概念,MEF 支持其中的一些。MEF 支持几种导入类型,包括动态、延迟、必备和可选。
随附的源代码包含了一些我在本博客中未讨论的高级 MEF 编程概念。您可以逐行调试源代码并探索这些概念。
动态导入
.NET 4.0 引入了一个新类型,即 `dynamic`。该类型是 `static` 类型,但 `dynamic` 类型的对象会绕过 `static` 类型检查。在大多数情况下,它的功能类似于 `type` 对象。在编译时,类型为 `dynamic` 的元素被假定支持任何操作。因此,您不必担心对象是从 COM API、动态语言(如 IronPython)、HTML 文档对象模型 (DOM)、反射还是程序中的其他位置获取其值的。但是,如果代码无效,则会在运行时捕获错误。
在某些情况下,导入类可能希望匹配具有特定约定名称的任何类型的导出。在这种情况下,该类可以声明一个动态导入。以下导入匹配具有约定名称“DemoOfDynamicImport
”的任何导出。
1 [Import("DemoOfDynamicImport")]
2 public dynamic somedynamicclassobject;
当约定类型从 `dynamic` 关键字推断出来时,它将匹配任何约定类型。在这种情况下,导入**始终**应指定一个要匹配的约定名称。(如果未指定约定名称,则导入将被视为不匹配任何导出。)以下两个导出都会匹配前面的导入。导入类必须准备好处理任意类型的对象。
1 [Export("DemoOfDynamicImport", typeof(IGreeting))]
2 public class DemoOfDynamicImportClass
3 {
4 public string SayHelloWorld()
5 {
6 return "Hello from DemoOfDynamicImport Class";
7 }
8 }
延迟导入
在某些情况下,导入类可能需要对导入对象的间接引用,以便不立即实例化该对象。在这种情况下,该类可以通过使用 `Lazy
1 [Import("IMyLazyClass",AllowDefault = true)]
2 public Lazy<MyLazyClass> objlazyclass;
3
4 [ImportMany]
5 public Lazy<IGreeting>[] Greetings1 { get; set; }
6
7 [ImportMany]
8 public IEnumerable<Lazy<IGreeting>> Greetings2 { get; set; }
从组合引擎的角度来看,`Lazy
1 [Export("IMyLazyClass")]
2 class MyLazyClass
3 {
4 public string SayHelloWorld()
5 {
6 return "Hello from MyLazyClass";
7 }
8 }
以下 `Export` 代码匹配上面 `Import` 代码的第 4 行或第 7 行的 `Import`。可以在 `Import` 属性中为延迟 `import` 指定约定名称和约定类型。
1 [Export(typeof(IGreeting))]
2 public class SimpleGreetingClass : IGreeting
3 {
4 public string SayHelloWorld()
5 {
6 return "Hello World !!!";
7 }
8
9 //Explicitly specifying a generic type.
10 [Export(typeof(Func<int, string>))]
11 public string DoSomething(int TheParam)
12 {
13 return "From Func: You Entered " + TheParam.ToString();
14 }
15 }
可选导入
Import
属性指定了部件正常运行的要求。如果导入无法满足,该部件的组合将失败,该部件将不可用。您可以使用 `AllowDefault` 属性指定 `import` 是可选的。在这种情况下,即使 `import` 未匹配任何可用导出,组合也会成功,并且导入属性将被设置为其属性类型的默认值(对象属性为 `null`,布尔值为 `false`,数字属性为零)。以下类使用了一个可选导入。
1 [Import("IMyLazyClass", AllowDefault = true)]
2 public Lazy<MyLazyClass> objlazyclass;
元数据
Export
可以提供有关它们自身的额外信息,称为元数据。元数据可用于将导出对象属性传达给导入部件。导入部件可以使用这些数据来决定使用哪些 `export`,或在不构造 `export` 的情况下收集有关 `export` 的信息。因此,`import` 必须是延迟的才能使用元数据。要使用元数据,通常会声明一个称为元数据视图的接口,该接口声明将提供哪些元数据。元数据视图接口只能包含属性,并且这些属性必须具有 get 访问器。为了允许访问元数据,MEF 利用了 .NET Framework 4 的一个新 API `System.Lazy
以下类是元数据的示例。请参见第 25 行。
1 using System;
2 using System.ComponentModel.Composition;
3 using ContractsLibrary;
4
5 namespace MEFPart1
6 {
7 [Export(typeof(IGreeting))]
8 public class SimpleGreetingClass : IGreeting
9 {
10 public string SayHelloWorld()
11 {
12 return "Hello World !!!";
13 }
14
15 //Explicitly specifying a generic type.
16 [Export(typeof(Func<int, string>))]
17 public string DoSomething(int TheParam)
18 {
19 return "From Func: You Entered " + TheParam.ToString();
20 }
21 }
22
23
24 [Export(typeof(IGreeting))]
25 [ExportMetadata("Name", "Kishore")]
26 public class SimpleMetaDataClass : IGreeting
27 {
28 public string SayHelloWorld()
29 {
30 return "Hello World from SimpleMetaDataClass.
Checking the metadata name at runtime !!!";
31 }
32 }
33 }
以下类是元数据的示例。请参见第 11 行。
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.ComponentModel.Composition;
6 using ContractsLibrary;
7
8 namespace MEFPart2
9 {
10 [Export(typeof(IGreeting))]
11 [ExportMetadata("Name", "Babu")]
12 public class ExtendedGreeting : IGreeting
13 {
14 public string SayHelloWorld()
15 {
16 return "Hello " + Environment.UserDomainName + "\\" +
Environment.UserName;
17 }
18 }
19
20 //[PartNotDiscoverable]
21 // A part decorated with PartNotDiscoverabl attribute
// will not be included in any catalogs.
22 //So in the main exe, you will get runtime composition error
23 [Export("DemoOfDynamicImport", typeof(IGreeting))]
24 public class DemoOfDynamicImportClass
25 {
26 public string SayHelloWorld()
27 {
28 return "Hello from DemoOfDynamicImport Class";
29 }
30 }
31 }
带有元数据的 `import` 被声明为一个延迟导入,并将元数据接口作为 `Lazy
1 [ImportMany]
2 public IEnumerable<Lazy<IGreeting, IGreetingMetadata>> greetingmetadata
一旦导入了带有元数据的延迟导出集合,就可以使用 LINQ(已注释掉)对其进行过滤,如以下代码片段所示。
1 foreach (Lazy<IGreeting, IGreetingMetadata>
greetingmeta in greetingmetadataobjects)
2 {
3 if (greetingmeta.Metadata.Name == "Kishore")
4 {
5 Console.WriteLine(greetingmeta.Value.SayHelloWorld());
6 //or we can create an object depending on the metadata value at runtime
7 IGreeting objgreeting = greetingmeta.Value;
8 Console.WriteLine(objgreeting.SayHelloWorld());
9 }
10 }
11
12 ////The below commented code also performs the same task as the following code.
13 ////Following is the code incase, you want to create an object of a class using LINQ
14 //IEnumerable<IGreeting> objgreeting = greetingmetadataobjects.Where
(v => v.Metadata.Name.Equals("Kishore")).Select(v => v.Value);
15 //foreach (var greeting in objgreeting)
16 //{
17 // if (greeting != null)
18 // {
19 // Console.WriteLine(greeting.SayHelloWorld());
20 // }
21 //}
源代码可在以下位置找到:
Microsoft: http://cid-38ecce05b21b8b44.office.live.com/self.aspx/MY%20Projects/All%20MEF%20Concepts.zip
“不要走别人走过的路,而是去没有路的地方,并留下你的足迹。”
分类: 高级 MEF 概念, CodeProject, MEF
