Managed Extensibility Framework 在.NET 4.5中有若干改进,这些都是源自于开源社区的推动(http://mef.codeplex.com/)。
这改动包括:对泛型类型的支持、多作用域及对基于约定编程模型的支持。
什么样的代码才算是基于约定的呢,其实在MS其它框架中也有所体现,比如ASP.NET MVC中 Url Routing /EF 4.1+的Fluent API的配置方式都可以算做基于约定的。
话说MEF之前是用声明式的Attribute来搞定代码的:
1 class Util 2 { 3 [Import] 4 public SubUtilA A { get; set; } 5 [Import] 6 public SubUtilB B { get; set; } 7 } 8 [Export] 9 class SubUtilA { } 10 [Export] 11 class SubUtilB { }
这样写当然没有什么问题,Attribute的形式看起来也很清爽,但是这样写总会有些问题:
- 扩展更多类型时总是要加上Export和Import的Attribute
- 看起来类不是那么纯了,特别是处女座的同学
那么.NET 4.5中基于约定的模型可以让我们怎么来搞定这俩问题呢?
1 class Util 2 { 3 public SubUtilA A { get; set; } 4 public SubUtilB B { get; set; } 5 } 6 class SubUtilA { } 7 class SubUtilB { }
这些是类型定义,我们不添加Attribute
然后里,我们定义一个约定
1 var builder = new RegistrationBuilder(); 2 builder 3 .ForTypesMatching(c => c.Name.StartsWith("SubUtil")) 4 .Export(); 5 builder 6 .ForType<Util>() 7 .Export() 8 .ImportProperties(c => c.Name.Length == 1);
嗯,导出所有SubUtil开头的类,然后在Util中Import所有长度是1的属性
通过这样简单的规则,在再次添加新的类型的时候就可以不额外添加或改动多余代码了。
当然,这种规则定义还可以更加多彩,有待你发现
ALL Code:


1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel.Composition; 4 using System.ComponentModel.Composition.Hosting; 5 using System.ComponentModel.Composition.Registration; 6 using System.Linq; 7 using System.Text; 8 using System.Threading.Tasks; 9 10 namespace ConsoleApplication1 11 { 12 class Program 13 { 14 static void Main(string[] args) 15 { 16 var builder = new RegistrationBuilder(); 17 builder 18 .ForTypesMatching(c => c.Name.StartsWith("SubUtil")) 19 .Export(); 20 builder 21 .ForType<Util>() 22 .Export() 23 .ImportProperties(c => c.Name.Length == 1); 24 var cat = 25 new AssemblyCatalog(typeof(Program).Assembly, builder); 26 var container = new CompositionContainer(cat); 27 28 var u = container.GetExportedValue<Util>(); 29 Console.ReadKey(); 30 31 } 32 } 33 34 class Util 35 { 36 public SubUtilA A { get; set; } 37 public SubUtilB B { get; set; } 38 } 39 class SubUtilA { } 40 class SubUtilB { } 41 42 43 //class Util 44 //{ 45 // [Import] 46 // public SubUtilA A { get; set; } 47 // [Import] 48 // public SubUtilB B { get; set; } 49 //} 50 //[Export] 51 //class SubUtilA { } 52 //[Export] 53 //class SubUtilB { } 54 55 }