好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

使用MEF实现IOC

使用MEF实现IOC

使用MEF实现IOC

〇、目录

一、 前言

  (一) 什么是IOC

  (二) 什么是MEF

  (三) 为什么选择MEF

二、 准备工作

三、 MEF在桌面程序中的使用

四、 MEF在MVC中的使用

五、 总结

六、 源码下载

一、前言 (一)什么是IOC

  什么是IOC?基本含义是:当某个角色(调用者)需要另一个角色(被调用者)的协助时,在传统程序设计过程中,通常由调用者来创建被调用者的实例。但在加入IOC组件后,创建被调用者实例的工作不再由调用者来完成,而是将由IOC组件来自动完成,然后注入调用者。

  网上已经非常非常多的介绍资料了,这里就不赘述了,这里给出几篇参考:

百度百科:控制反转 依赖注入(IOC) (二)什么是MEF

Managed Extensibility Framework 或 MEF 是一个用于创建可扩展的轻型应用程序的库。   应用程序开发人员可利用该库发现并使用扩展,而无需进行配置。   扩展开发人员还可以利用该库轻松地封装代码,避免生成脆弱的硬依赖项。   通过 MEF,不仅可以在应用程序内重用扩展,还可以在应用程序之间重用扩展。

   

  下面这篇文章对MEF的介绍非常到位:

Managed Extensibility Framework概述 体验Managed Extensibility Framework精妙的设计

(三)为什么选择MEF

  已经有很多很好的诸如Unity,Autofac,Ninject,Spring.Net等等IOC组件了,为什么我还要推荐使用MEF呢,下面是我推荐的理由:

.net4.0自带,非第三方组件 0配置,没有像其他IOC组件那样需要复杂的外部配置支持 使用非常简单的方式来提供具有强大灵活性的可扩展性支持

二、准备工作

  本文案例很简单,一个接口

  这个接口的实例类

  我们要做的工作就是要通过MEF来解除业务使用者对具体业务实现的依赖关系。

要使用MEF,需添加 System.ComponentModel.Composition 类库的引用

与其他通过外部配置文件来完成接口与实现类的对应关系的IOC组件不同,MEF是通过 ExportAttribute 特性来完成的(如有多个实现,可加入别名来区分),如下图所示:

三、MEF在桌面程序中的使用

  在桌面程序中,需要完成两个部分的目录匹配,一个是dll中的匹配,另一个为exe程序集中的匹配,分别使用到DirectoryCatalog与AssemblyCatalog两个目录类。而两个目录类需加入到 AggregateCatalog 目录类中,才能参与组合容器CompositionContainer的初始化。

在调用方,只需要使用 ImportAttribute 特性来注入即可获得被调用者的实例



由于这里调用方法是静态方法,手动从组合容器中获取 调用者HomeBusiness类的实例

输出,得到了业务实现类 HomeService返回的结果

四、MEF在MVC中的使用

   在MVC的项目中,IOC组件是通过 DependencyResolver类中的 SetResolver(IDependencyResolver resolver) 方法来向MVC提供注册点的,所以我们只需要实现一个 IDependencyResolver 接口的MEF实现类,即可完成MEF在MVC中的注册工作。

  另外考虑到Web应用程序的无状态性,即每次访问都是独立进行的,所以IOC组件产生的对象实例也必须唯一,否则不同用户的操作就可能串线,产生相互干扰。在这里,我们使用HttpContext.Current.Items集合来保存 组合容器CompositionContainer的实例,以使每个用户的数据保持独立,并且同一用户的同一个Http请求中使用同一对象实例。

  MefDependencySolver实现代码如下:

  1   namespace   Liuliu.Demo.Site.Web.Helper.Ioc
   2   {
   3       public   class   MefDependencySolver : IDependencyResolver
   4       {
   5           private   readonly   ComposablePartCatalog _catalog;
   6           private   readonly   string  _httpContextKey =  Guid.NewGuid().ToString();
   7  
  8           public   MefDependencySolver(ComposablePartCatalog catalog)
   9           {
  10              _catalog =  catalog;
  11           }
  12  
 13           public   CompositionContainer Container
  14           {
  15               get 
 16               {
  17                   if  (! HttpContext.Current.Items.Contains(_httpContextKey))
  18                   {
  19                      HttpContext.Current.Items.Add(_httpContextKey,  new   CompositionContainer(_catalog));
  20                   }
  21                  CompositionContainer container =  (CompositionContainer)HttpContext.Current.Items[_httpContextKey];
  22                  HttpContext.Current.Application[ "  Container  " ] =  container;
  23                   return   container;
  24               }
  25           }
  26  
 27           #region  IDependencyResolver Members
 28  
 29           public   object   GetService(Type serviceType)
  30           {
  31               string  contractName =  AttributedModelServices.GetContractName(serviceType);
  32               return  Container.GetExportedValueOrDefault< object > (contractName);
  33           }
  34  
 35           public  IEnumerable< object >  GetServices(Type serviceType)
  36           {
  37               return  Container.GetExportedValues< object > (serviceType.FullName);
  38           }
  39  
 40           #endregion 
 41       }
  42  }

在Global.asax.cs的Application_Start方法中初始化MEF容器,由于Web应用程序中只需要在DLL中查找匹配,所以只使用DirectoryCatalog即可。

作为调用者,Controller中同样需要添加被调用者的注入信息

  1   namespace   Liuliu.Demo.Site.Web.Controllers
   2   {
   3       [Export]
   4       public   class   HomeController : Controller
   5       {
   6           [Import]
   7           public  IHomeContract HomeContract {  get ;  set  ; }
   8  
  9           public   ActionResult Index()
  10           {
  11               string  data =  HomeContract.GetData();
  12               return   Content(data);
  13           }
  14       }  
  15  }

执行程序,同样输出了HomeService的返回数据:

五、总结

  MEF不同于 显式注册可用组件的做法 ,在MEF中组件被视为部件。这些部件主要有“导入”(Import)部件和“导出”(Export)部件,此外MEF提供了一个组合容器(ComposeContainer),容器会发现指定Catalog的导入导出部件,并按Contract(协定)、Metadata(元数据)等对导入和导出部件进行组合。

上述文字已经把MEF中涉及的相关概念指出了,下面具体说明一下:

Export(导出): “Export”也就是我们常说的组件或者模块或者服务,它是部件向容器中的其他部件提供的一个值、功能或服务等;

Import(导入): "Import”,既扩展点,是组件,服务等接入系统的窗口 , 是部件向要通过可用导出满足的容器提出的要求, MEF 支持若干导入类型,其中包括动态导入、延迟导入、必备导入和可选导入 ;

Contract(协定): 是Export和Import的一种约定,一种协议, 只有Contract相匹配的Import和Export部件才能组装成功;

Catalog(目录): 为了发现可用于组合容器的部件,组合容器将使用“Catalog”。   目录是一个对象,通过它发现可用部件,   MEF 提供了用于从提供的类型、程序集或磁盘路径创建Catalog。

Compose(组合):在MEF中,容器将导入与导出匹配的这一过程我们称之为组合, 部件由 MEF 组合,MEF 将部件实例化,然后使导出程序与导入程序相匹配。

六、源码下载

LiuliuFrameworkDemo01_MEF.rar

 

 

分类:  MVC ,  架构设计

标签:  MVC ,  架构设计

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于使用MEF实现IOC的详细内容...

  阅读:34次