《电子技术应用》
您所在的位置:首页 > 嵌入式技术 > 设计应用 > IoC模式及其应用
IoC模式及其应用
2016年微型机与应用第06期
(沙洲职业工学院,江苏 张家港 215600)
摘要: IoC是一种优秀的组件解耦模式,而依赖注入是IoC最流行的实现方式。探讨了依赖注入的三种不同的实现方式:构造器注入、属性注入以及接口注入,并介绍了IoC容器Unity的基本使用方法。
Abstract:
Key words :

  周洪斌

  (沙洲职业工学院,江苏 张家港 215600)

      摘要:IoC是一种优秀的组件解耦模式,而依赖注入是IoC最流行的实现方式。探讨了依赖注入的三种不同的实现方式:构造器注入、属性注入以及接口注入,并介绍了IoC容器Unity的基本使用方法。

  关键词依赖倒置原则控制反转;依赖注入;Unity

0引言

  2015年江苏省高校大学生创新创业训练计划立项项目(201511288009Y)在使用简单三层架构开发数据库应用程序时,一般都是在业务逻辑层直接创建数据访问层相应的对象,如:

  public class ProductBLL

  {

  SqlServerDAL dal = new SqlServerDAL();

  public int Add(ProductModel model)

  {

  return dal.Add(model);

  }

  }

  这种方式下由调用者ProductBLL主动创建被依赖对象SqlServerDAL,然后调用被依赖对象的方法,导致调用者与被依赖对象实现类的硬编码耦合,不利于项目的维护与升级。上述紧耦合的业务逻辑层与数据访问层的关系如图1所示。

  

001.jpg

  如果用户需要将数据库换成Access或者MySQL,需要修改ProductBLL类内部的代码,违反了开放封闭原则。开放封闭原则要求“软件实体(类、模块、函数等)对扩展是开放的,对修改是封闭的”。依赖倒置原则(Dependency Inversion Principle,DIP)要求“高层模块不应该依赖于低层模块,两者应该依赖于抽象”[1]。因此,业务逻辑层的对象不应该直接依赖于数据访问层的具体实现对象,而应该通过数据访问层的抽象接口进行访问,如图2所示。通过引入抽象,对于高层模块而言,低层模块的实现是可替换的。这实际上也是“开放封闭原则”的体现。

  

002.jpg

1控制反转

  DIP作为一种软件设计原则,指明了两个模块之间应该如何依赖。而控制反转(Inversion of Control,IoC)则是一种具体的软件设计模式,明确了如何解除相互依赖的模块之间的耦合。IoC是指应用本身不负责依赖对象的创建和维护,而交给一个外部容器来完成。这样就将控制权由应用转移到了外部,实现了控制权的反转[2]。IoC的作用在于降低组件之间的耦合度,减少组件之间的依赖关系,提高程序的灵活性和可维护性。

  依赖注入(Dependency Injection,DI)是IoC模式最流行的实现方式,即由外部容器在运行时动态地将依赖的对象注入到组件中。通过依赖注入,业务逻辑层将不再需要直接创建数据访问层的对象,从而降低了两者之间的耦合度。

2依赖注入

  依赖注入提供一种机制,将需要依赖(低层模块)对象的引用传递给被依赖(高层模块)对象。具体的依赖注入可以分为三种形式,即构造器注入、属性注入以及接口注入[3]。

  2.1构造器注入

  构造器注入,即通过构造方法传递依赖。根据依赖倒置原则,高层模块不应该依赖于低层模块,两者应该依赖于抽象。因此构造方法的参数应该是一个抽象类型。

  首先,需要定义一个接口IDataAccess,并在IDataAccess接口中声明一个Add方法,代码如下:

  public interface IDataAccess

  {

  int Add(ProductModel model);

  }

  然后,在SqlServerDAL类中,实现IDataAccess接口,代码如下:

  public class SqlServerDAL:IDataAccess

  {

  public int Add(ProductModel model)

  {

  //省略具体数据库操作代码

  }

  }

  接下来,修改ProductBLL类的代码,代码如下:

  public class ProductBLL

  {

  private IDataAccess dal;

  //构造器注入

  public ProductBLL(IDataAccess dal)

  {

  this.dal=dal;//传递依赖

  }

  public int Add(ProductModel model)

  {

  return dal.Add(model);

  }

  }

  在这里,将依赖对象SqlServerDAL对象的创建和绑定转移到ProductBLL类的外部来实现,这样就解除了两者之间的紧耦合关系。这时,如果要将数据库换成Access数据库时,只需定义一个AccessDAL类,实现IDataAccess接口,然后在外部重新绑定依赖,不需要修改ProductBLL类内部代码即可实现对Access数据库的操作。

  2.2属性注入

  属性注入,即通过属性来传递依赖。因此,首先需要在依赖类ProductBLL中定义一个属性,代码如下:

  public class ProductBLL

  {

  private IDataAccess dal;

  //属性,接受依赖

  public IDataAccess Dal

  {

  set { dal = value; }

  get { return dal; }

  }

  public int Add(ProductModel model)

  {

  return dal.Add(model);

  }

  }

  然后在外部通过给Dal属性赋值,从而传递依赖。

  2.3接口注入

  接口注入需要先定义一个接口,包含一个设置依赖的方法。然后由依赖类继承并实现这个接口。

  首先定义一个接口,代码如下:

  public interface IDependent

  {

  void SetDependence(IDataAccess dal);//设置依赖项

  }

  依赖类实现这个接口,代码如下:

  public class ProductBLL:IDependent

  {

  private IDataAccess dal;

  //实现接口

  public void SetDependence(IDataAccess dal)

  {

  this.dal = dal;

  }

  public int Add(ProductModel model)

  {

  return dal.Add(model);

  }

  }

  外部则通过SetDependence方法传递依赖。相比构造器注入和属性注入,接口注入显得有些复杂,使用也不常见。

3IoC容器

  3.1IoC容器概述

  一般在小型项目中可以手动创建依赖对象,并将引用传递给被依赖模块。如:

  IDataAccess dal=new SqlServerDAL();//在外部创建依赖对象

  ProductBLL bll=new ProductBLL(dal);//通过构造器注入依赖

  对于大型项目来说,相互依赖的组件比较多,如果还用手动的方式来创建和注入依赖,效率较低。正因如此,IoC容器诞生了。IoC容器实际上是一个依赖注入框架,它包含以下几个功能:

  (1)动态创建、注入依赖对象;

  (2)管理对象生命周期;

  (3)映射依赖关系。

  Spring是Java平台广泛使用的IoC容器[4],.NET平台常用的IoC容器包括Unity、Autofac、Spring.NET和Ninject等。Unity是微软公司推出的一款轻量的、可扩展的依赖注入容器,该项目在Codeplex上的地址为http://unity.codeplex.com,可以下载相应的安装包和开发文档[5]。

  3.2Unity应用

  Unity在实际项目中的使用方法如下[6]:

  (1)添加对Microsoft.Practices.Unity.dll、Microsoft.Practices.Unity.Configuration.dll以及Microsoft.Practices.Unity.RegistrationByConvention.dll的引用。

  (2)在项目配置文件的<configSections>节点下注册名为unity的section,并在<configuration>节点下添加unity配置信息。配置文件样例如下:

  <?xml version="1.0" encoding="utf-8" ?>

  <configuration>

  <configSections>

  <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,Microsoft.Practices.Unity.Configuration"/>

  </configSections>

  <unity>

  <container name="MyContainer">

  <!--映射关系-->

  <register type="UnityDemo.IDataAccess,UnityDemo"mapTo="UnityDemo.SqlServerDAL,UnityDemo"></register>

  </container>

  </unity>

  <startup>

  <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />

  </startup>

  </configuration>

  (3)在代码中读取配置信息,并将配置载入到UnityContainer中。

  //创建容器

  IUnityContainer container = new UnityContainer();

  //载入配置信息

  container.LoadConfiguration("MyContainer");

  //获取指定名称的配置节

  UnityConfigurationSection section

  = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");

  //获取特定配置节下已命名的配置节<container name='MyContainer'>下的配置信息

  section.Configure(container, "MyContainer");

  //创建实现了IDataAccess接口的对象

  IDataAccess dal = container.Resolve<IDataAccess>();

4结论

  IoC能有效降低组件之间的耦合度,提高程序的灵活性和可扩展性。本文围绕如何实现业务逻辑层与数据访问层之间的松散耦合,介绍了构造器注入、属性注入以及接口注入三种不同的依赖注入方式,并介绍了NET平台下常用IoC容器Unity的使用,展示了IoC在软件开发领域的实际应用。

参考文献

  [1] 张逸.软件设计精要与模式(第2版)[M].北京:电子工业出版社,2010.

  [2] 王程,周安琳.基于Autofac对乳制品安全风险预警系统的扩展设计[J].河北省科学院学报,2013,30(1):14.

  [3] 张浩.利用反向控制原则和依赖注入的可复用框架设计解耦方法[J].计算机应用,2010(12):227229.

  [4] 周岚.基于Spring框架的IoC模式的设计和实现[J].合肥学院学报(自然科学版),2011,21(1):4953.

  [5] 李凤桐.微软企业库组件Unity使用浅析[J].电脑编程技巧与维护,2015(6):1314.

  [6] 蒋金楠.ASP.NET MVC4框架揭秘[M].北京:电子工业出版社,2013.


此内容为AET网站原创,未经授权禁止转载。