第一次接触IoC是我在学习MVP框架的时候,搭建一个MVP框架需要用到IoC,那时候就以为IoC就是依赖注入,但在后来的逐步了解中发现那个只是它的别名而已。IoC全称应该是Inversion of Control,中文称为控制反转;而依赖注入的简称是DI,全称是Dependency Injection,个人觉得这两者也不是那么一个别名的关系而已,控制反转给我的感觉更多的是一种思想,而依赖注入却正好是一种实现方式。那这里说说概念

  • 控制反转:应用本身不负责以来对象的维护和创建,而交给一个外部容器来负责。这样控制权就由应用转到了外部IoC容器,控制权就实现了所谓的反转。
  • 依赖注入:由外部容器在运行时动态地将以来的对象注入到组件中。

以上概念摘自蒋老师的著作《ASP.NET MVC4 框架揭秘》。但是技术这东西又没必要向理论学术那样严谨,能让人知晓其中意图则可,最初UML最初创作处理也是为了达到这个目的。

  高内聚低耦合一直是软件开发中不断追求的,现在各种框架MVC,MVP等都是为了解耦而诞生的。在我阅读微软的开源项目PetShop时发现里面用了耳熟能详的三层架构中使用了最初我学C#时不知有什么作用的一个东西——接口Interface。它的存在很大的目的就是为了解耦,它能使一些比较具体的事物抽象化。那么本篇所讨论的IoC也是使用了接口。

目前有很多IoC框架:Unity,Spring.NeT,Ninject,StructureMap等。Ninject在我实践MVP的时候用过,Unity在我阅读蒋老师的著作时了解过,那么这回我将会尝试一下之前没用过的Unity,体验一下依赖注入。

模拟使用一个三层架构来体验这个Unity

定义DAL,BLL,UI层的接口IDAL,IBLL,IUI以及实现它们的类DAL,BLL,UI。

     interface IDAL
{
DataTable QueryDatas();
}
interface IBLL
{
List<object> GetSomeDatas();
} interface IUI
{
void ShowData(IBLL bll);
} class DAL : IDAL
{ public DataTable QueryDatas()
{
DataTable table = new DataTable();
table.Columns.Add("Col");
for (int i = ; i < ; i++)
{
table.Rows.Add(i);
}
return table;
}
}
class BLL : IBLL
{
[Dependency]
public IDAL dal { get; set; } public List<object> GetSomeDatas()
{
List<object> result = new List<object>();
DataTable table = dal.QueryDatas();
foreach (DataRow row in table.Rows)
{
result.Add(row[]);
}
return result;
}
}
class UI : IUI
{
[InjectionMethod]
public void ShowData(IBLL bll)
{
List<object> datas = bll.GetSomeDatas();
foreach (object item in datas)
{
Console.WriteLine(item);
}
}
}

在上面的代码中BLL类的dal属性使用了[Dependency] Attribute,使得该属性是通过IoC容器自动去赋值,不需要通过代码给它显示赋值。UI的ShowData方法用了[InjectionMethod] Attribute,该方法在UI类被IoC容器自动执行。实际上上面代码设计到IoC里面三种方式的其中两种属性注入和接口(方法)注入,那么还剩下一种就是构造器注入,

  • 在上面使用了Dependency  Attribute的IDAL属性则是使用属性注入,使用了依赖注入的属性在IoC容器构造对象的时候自动初始化赋值;
  • 上面使用了InjectionMethod Attribute的ShowData方法则是使用接口(方法)注入,使用了依赖注入的方法在IoC容器构造对象的时候自动执行该方法;
  • 还有一种没有列举出来的就是构造器注入, IoC容器会自动选择和调用合适的构造函数以创建依赖的对象。如果被选择的构造函数是带参数的,IoC容器是会去创建该参数的实例的。上面的代码还没可以执行,需要在配置文件中添加以下内容
 <configuration>
<configSections>
<section name="unity"
type="
Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
Microsoft.Practices.Unity.Configuration"/>
</configSections>
<unity>
<containers>
<container name="defaultContainer">
<register type="AllTypeTestControl.IDAL,AllTypeTestControl" mapTo="AllTypeTestControl.DAL,AllTypeTestControl"/>
<register type="AllTypeTestControl.IBLL,AllTypeTestControl" mapTo="AllTypeTestControl.BLL,AllTypeTestControl"/>
<register type="AllTypeTestControl.IUI,AllTypeTestControl" mapTo="AllTypeTestControl.UI,AllTypeTestControl"/>
</container>
</containers>
</unity>
</configuration>

上面这段内容是指定了给Unity的IoC容器各个接口与实现类的映射关系,AllTypeTestControl.IDAL类型映射到AllTypeTestControl.DAL中去,表示通过DAL来实现IDAL的注入,其他同理。但每一项的注册要按照

<register type="接口全名,程序集名" mapTo="类全名,程序集名"/> 

通过下面的测试代码来测试

         public static void TestMain()
{
IUnityContainer container = new UnityContainer();
UnityConfigurationSection configuration =
ConfigurationManager.GetSection(UnityConfigurationSection.SectionName)
as UnityConfigurationSection;
configuration.Configure(container, "defaultContainer");
UI ui = container.Resolve<IUI>() as UI ;
}

主要是构造了一个IoC的容器,然后载入了配置文件的映射信息,除了通过配置文件来确定映射关系外,还可以通过代码的形式来确定

        public static void TestMain()
{
IUnityContainer container = new UnityContainer();
container.RegisterType<IDAL, DAL>();
container.RegisterType<IBLL, BLL>();
container.RegisterType<IUI, UI>();
UI ui = container.Resolve<IUI>() as UI ;
}

代码的运行结果如下

现在则把上面的BLL作一下修改

     class BLL : IBLL
{
//[Dependency]
//public IDAL dal { get; set; } private IDAL dal; //[InjectionConstructor]
public BLL(IDAL dal)
{
this.dal = dal;
} //[InjectionConstructor]
public BLL()
{ } public List<object> GetSomeDatas()
{
List<object> result = new List<object>();
DataTable table = dal.QueryDatas();
foreach (DataRow row in table.Rows)
{
result.Add(row[]);
}
return result;
}
}

结果仍然和上面的一样,IoC容器仍然能正确的匹配出类型构造了DAL对象。那么如果给BLL()构造函数加了InjectionConstructor Attribute,IoC容器只会去匹对带了InjectionConstructor Attribute的构造函数,这样BLL(IDAL dal)构造函数则不会被调用,运行起来就会抛出空引用异常。假如给BLL(IDAL dal)也加上了InjectionConstructor Attribute,那么它与无参构造函数BLL()属于同级,IoC则会也调用BLL(IDAL dal)构造函数,dal字段能被正常的赋值。

  通过上面的实践中能感觉到IoC有GOF中的工厂模式思想。用户在使用着一个对象,但它并不负责对象的构造,把对象的构造移交了给第三方,在IoC中就是IoC容器,在工厂方法里面则是工厂了。在ASP.NET MVC中也使用了IoC,迷你MVC框架中控制器的构造是通过了一个工厂利用反射机制来构造出来的,而实际的ASP.NET MVC则是使用了IoC。

  对IoC的了解还不算多,手上有一份Ninject的源码,但一直没看,现在工作忙了,连博客也少写了,时间得好好分配,要保持学习。以上有什么说的不对的请指正,有什么好的建议或意见也请分享,谢谢!

认识IoC的更多相关文章

  1. 学习AOP之透过Spring的Ioc理解Advisor

    花了几天时间来学习Spring,突然明白一个问题,就是看书不能让人理解Spring,一方面要结合使用场景,另一方面要阅读源代码,这种方式理解起来事半功倍.那看书有什么用呢?主要还是扩展视野,毕竟书是别 ...

  2. 【调侃】IOC前世今生

    前些天,参与了公司内部小组的一次技术交流,主要是针对<IOC与AOP>,本着学而时习之的态度及积极分享的精神,我就结合一个小故事来初浅地剖析一下我眼中的“IOC前世今生”,以方便初学者能更 ...

  3. 深入理解DIP、IoC、DI以及IoC容器

    摘要 面向对象设计(OOD)有助于我们开发出高性能.易扩展以及易复用的程序.其中,OOD有一个重要的思想那就是依赖倒置原则(DIP),并由此引申出IoC.DI以及Ioc容器等概念.通过本文我们将一起学 ...

  4. 自己实现简单Spring Ioc

    IoC则是一种 软件设计模式,简单来说Spring通过工厂+反射来实现IoC. 原理简单说明: 其实就是通过解析xml文件,通过反射创建出我们所需要的bean,再将这些bean挨个放到集合中,然后对外 ...

  5. 使用Microsoft的IoC框架:Unity来对.NET应用进行解耦

    1.IoC/DI简介 IoC 即 Inversion of Control,DI 即 Dependency Injection,前一个中文含义为控制反转,后一个译为依赖注入,可以理解成一种编程模式,详 ...

  6. DIP原则、IoC以及DI

    一.DIP原则 高层模块不应该依赖于底层模块,二者都应该依赖于抽象. 抽象不应该依赖于细节,细节应该依赖于抽象. 该原则理解起来稍微有点抽象,我们可以将该原则通俗的理解为:"依赖于抽象&qu ...

  7. 【初探Spring】------Spring IOC(三):初始化过程---Resource定位

    我们知道Spring的IoC起到了一个容器的作用,其中装得都是各种各样的Bean.同时在我们刚刚开始学习Spring的时候都是通过xml文件来定义Bean,Spring会某种方式加载这些xml文件,然 ...

  8. 【初探Spring】------Spring IOC(二):初始化过程---简介

    首先我们先来看看如下一段代码 ClassPathResource resource = new ClassPathResource("bean.xml"); DefaultList ...

  9. 【初探Spring】------Spring IOC(一)

    IOC:Inversion of Control(控制反转).IOC它所体现的并不是一种技术,而是一种思想,一种将设计好的对象交给容器来管理的思想.IOC的核心思想就体现在控制.反转这两个词上面,要理 ...

  10. .NET里简易实现IoC

    .NET里简易实现IoC 前言 在前面的篇幅中对依赖倒置原则和IoC框架的使用只是做了个简单的介绍,并没有很详细的去演示,可能有的朋友还是区分不了依赖倒置.依赖注入.控制反转这几个名词,或许知道的也只 ...

随机推荐

  1. [ACM_动态规划] 嵌套矩形

    问题描述:有n个矩阵,每个矩阵可以用两个整数a,b来表示 ,表示他的长和宽,矩阵X (a,b) 可以 嵌套 到Y (c,d) 里面当且仅当 a < c &&  b < d  ...

  2. Atitit 图片 验证码生成attilax总结

    Atitit 图片 验证码生成attilax总结 1.1. 图片验证码总结1 1.2. 镂空文字  打散 干扰线 文字扭曲 粘连2 1.1. 图片验证码总结 因此,CAPTCHA在图片验证码这一应用点 ...

  3. Android笔记——Android五大布局

    一.五大布局 Android的界面是有布局和组件协同完成的,布局好比是建筑里的框架,而组件则相当于建筑里的砖瓦.组件按照布局的要求依次排列,就组成了用户所看见的界面.Android的五大布局分别是Li ...

  4. react7 react 三目运算

    <body><!-- React 真实 DOM 将会插入到这里 --><div id="example"></div> <!- ...

  5. angularjs的resource实例对象

    angularjs的resource实例对象 我们看看都有啥 而直接使用service对象的时候没有前面这些$

  6. Linux常用命令03

    上篇我们写到,如何编辑文件,我们有时候,在编辑的时候,有可能会异常的退出,这样的话, linux会针对这个文件生成一个swp文件,当你下次进入vi模式时,就会提示你一个错误 这样,即使你按enter键 ...

  7. XML学习笔记7——XSD实例

    在前面的XSD笔记中,基本上是以数据类型为主线来写的,而在我的实际开发过程中,是先设计好了XML的结构(元素.属性),并写好了一份示例,然后再反过来写XSD文件(在工具生成的基础上修改),也就是说,是 ...

  8. CSS隐藏元素的N种实现方式。

    1. width:0; 光有高度是不行的,还得有宽度.缺点文字隐藏不了,可以加个color:#fff和背景颜色一样就ok了,障眼法,迷惑人的,其实内容还在,如果有文字的话,还是可以触发点击事件的,这种 ...

  9. 利用border属性制作各种图形。

    这是一个比较正常的 但如果我们把宽度和高度去掉呢? 好像看不太出来对吧,我们来给边框加上不同颜色. 看出啥了没,分明就是每个边都是一个三角形啊. 那假如我想要一个朝下的三角形是不是我只要把border ...

  10. HTML5移动Web开发(十)——在浏览器中启动手机原生应用

    用户可以在浏览器中启动移动设备的原生应用程序,比如地图.电话.短信等,具体能够启动哪些应用程序,这取决于该移动设备上哪些原生应用是否允许从浏览器启动. 新建ch02r05.html <!doct ...