说起IOC,可能很多初学者不知道是用来做什么的,今天正好有点时间,就来扫扫盲,顺便巩固下自己。

IOC全称是Inversion Of Control,意为控制反转(这些自然百度也有),可什么是控制反转呢?

按我现在的理解,把上端依赖的项从细节转换为抽象,并把细节转移到第三方,这个就叫控制反转。

怎么理解呢?最简单的:我们有一个接口Ianimal,就像这样:

1
2
3
4
public interface iAnimal
    {
        void talk();
    }

然后我们现在用另一个类去实现该接口:

1
2
3
4
5
6
7
public class dog : iAnimal
    {
        public void talk()
        {
            Console.Write("小狗说:汪汪汪!");
        }
    }

然后呢,往常来讲,我们应该是这样调用的:

1
2
3
iAnimal dog = new dog();
dog.talk();
Console.ReadKey();

运行结果应该是这样的:

到目前为止都是正确的,相信各位小伙伴一般也是如此。

但请注意,我们在调用时是直接用dog类型new出来的,这种做法其实就已经依赖于细节了。

那么如何将这里依赖的细节修改为抽象呢?很简单,我们只需要一个工厂类帮助我们生成实际的类即可。

但是有些小伙伴可能想,工厂内也有细节啊,难道写个工厂就是IOC了么?

当然不是,我们还将细节交给配置文件(通过反射),这样在功能变动时,无需修改原代码,只需要修改配置文件即可。

工厂看上去是这样的:

1
2
3
4
5
6
7
8
9
10
public class SimpleFactory
    {
        public static iAnimal CreateAnimal()
        {
            string classModule = ConfigurationManager.AppSettings["PhoneType"];
            Assembly assembly = Assembly.Load(classModule.Split(',')[1]);
            Type type = assembly.GetType(classModule.Split(',')[0]);
            return (iAnimal)Activator.CreateInstance(type);
        }
    }

而我们的配置文件自然也要写点东西了:

1
2
3
<appSettings>
    <add key="AnimalType" value="IOCandDI.dog,IOCandDI"/>
</appSettings>

value内,逗号前是类的全限定名(命名空间+类名),后面是命名空间。

不会操作配置文件的小伙伴们,先添加这个引用:

然后引入System.Configuration命名空间就可以操作啦。

至于反射,直接引入System.Reflection 命名空间即可操作。反射的原理也很简单,在这里就不再赘述。

修改过后的调用和以前的调用对比:

1
2
3
4
5
6
iAnimal dog = new dog();
dog.talk();
 
iAnimal obj = SimpleFactory.CreateAnimal();
obj.talk();
Console.ReadKey();

结果是一样的:

这个时候,如果再多一种动物,只需要添加一个继承iAnimal接口的类,并且修改配置文件即可。

IOC带给我们的便利正是如此。

微软也推出了一款IOC的插件,叫做Unity,你在NuGet程序包管理中很轻松就能找到它:

首先是下载与安装:

然后在页面引入Microsoft.Practices.Unity就可以操作了,基本流程如下:

1
2
3
4
IUnityContainer container = new UnityContainer();//声明容器
container.RegisterType<iAnimal, cat>();//注册类型
iAnimal obj = container.Resolve<cat>();//完成实例
obj.talk();

运行效果:

了解了Unity的基础用法,我们在来看下如何利用Unity做依赖注入(DI——dependency injection)。

说到DI,就一定要知道DI的三种方式:属性注入、构造注入、方法注入。我这里直接改造了cat类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class cat : iAnimal
   {
       [Dependency]
       public iColor color { getset; }
       public iEat eat { getset; }
       public iRun run { getset; }
 
       [InjectionConstructor]
       public cat(iEat ieat)
       {
           eat = ieat;
       }
 
       public void talk()
       {
           Console.WriteLine("小猫说:喵喵喵!");
       }
 
       [InjectionMethod]
       public void Happy(iRun irun)
       {
           run = irun;
       }
   }

大家一定发现了我分别在属性、构造、方法头上加了特性。

实际上,Dependency、InjectionConstructor、InjectionMethod就是Unity中DI操作的标识符,它们分别对应属性注入、构造注入、方法注入。

那么,这些特性是如何帮助程序完成DI的呢?看调用代码:

1
2
3
4
5
6
7
8
9
10
11
12
IUnityContainer container = new UnityContainer();
container.RegisterType<iAnimal, cat>();
container.RegisterType<iColor, Color>();
container.RegisterType<iEat, Eat>();
container.RegisterType<iRun, Run>();
iAnimal obj = container.Resolve<cat>();
obj.talk();
cat myCat = (cat)obj;
Console.WriteLine("myCat.color是空的么?{0}", myCat.color == null);
Console.WriteLine("myCat.eat是空的么?{0}", myCat.eat == null);
Console.WriteLine("myCat.run是空的么?{0}", myCat.run == null);
Console.ReadKey();

在Unity容器内类型注册时,需注册cat类内3个参数的类型,用来对应3种注入方式。

运行结果如下:

3种注入方式都成功了~添加了特性的属性(或方法)在Unity容器执行实例时会自动寻找上面3个特性(的位置)并匹配注册类型(完成注入)。

需要注意的是,构造注入无需声明特性也可生效,Unity会自动寻找参数最多的构造参数进行注入(前提是被注入的参数类型一定要注册)。

ADD:在和一位小伙伴讨论时,他指出了我unity的使用方法有问题,我这里的确没有将unity容器的细节抽出到配置文件中(因为想着是基础使用教程就没有加),这一方面我也懒得再写,找到一篇介绍详细的博文供大家参考——http://www.cnblogs.com/junchu25/archive/2012/08/10/2631455.html

IOC详解和Unity基础使用介绍的更多相关文章

  1. NET笔记——IOC详解和Unity基础使用介绍

    说起IOC,可能很多初学者不知道是用来做什么的,今天正好有点时间,就来扫扫盲,顺便巩固下自己. IOC全称是Inversion Of Control,意为控制反转(这些自然百度也有),可什么是控制反转 ...

  2. Spring4 IOC详解

    Spring4 IOC详解 上一章对Spring做一个快速入门的教程,其中只是简单的提到了IOC的特性.本章便对Spring的IOC进行一个详解.主要从三个方面开始:基于xml文件的Bean配置,基于 ...

  3. IIS负载均衡-Application Request Route详解第一篇: ARR介绍(转载)

    IIS负载均衡-Application Request Route详解第一篇: ARR介绍 说到负载均衡,相信大家已经不再陌生了,本系列主要介绍在IIS中可以采用的负载均衡的软件:微软的Applica ...

  4. JAVASCRIPT事件详解-------原生事件基础....

    javaScirpt事件详解-原生事件基础(一)   事件 JavaScript与HTML之间的交互是通过事件实现的.事件,就是文档或浏览器窗口中发生的一些特定的交互瞬间,通过监听特定事件的发生,你能 ...

  5. 淘宝JAVA中间件Diamond详解(2)-原理介绍

    淘宝JAVA中间件Diamond详解(二)---原理介绍 大家好,通过第一篇的快速使用,大家已经对diamond有了一个基本的了解.本次为大家带来的是diamond核心原理的介绍,主要包括server ...

  6. 开源项目MultiChoiceAdapter详解(一)——概要介绍

    项目地址:https://github.com/ManuelPeinado/MultiChoiceAdapter 这个项目主要是提供了一个多选适配器,使用者可以用它来替换传统的适配器,用途还算比较广泛 ...

  7. IIS负载均衡-Application Request Route详解第一篇: ARR介绍

    IIS负载均衡-Application Request Route详解第一篇: ARR介绍 说到负载均衡,相信大家已经不再陌生了,本系列主要介绍在IIS中可以采用的负载均衡的软件:微软的Applica ...

  8. Spring IoC详解

    Spring IoC详解 1. 控制反转 控制反转是一种通过描述(XML或者注解)并通过第三方去产生或获取特定对象的方式.在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Depend ...

  9. 【Vue】详解组件的基础与高级用法

    Vue.js 最核心的功能就是组件(Component),从组件的构建.注册到组件间通信,Vue 2.x 提供了更多方式,让我们更灵活地使用组件来实现不同需求. 一.构建组件 1.1 组件基础 一个组 ...

随机推荐

  1. centos7 PDI(Kettle)安装

    kettle介绍 PDI(Kettle)是一种开源的 ETL 解决方案,书中介绍了如何使用PDI来实现数据的剖析.清洗.校验.抽取.转换.加载等各类常见的ETL类工作. 除了ODS/DW类比较大型的应 ...

  2. C#基础之数据类型

    c#有15个预定义类型,其中13个是值类型,两个是引用类型(string 和 object) 1.整型 2.浮点类型 float数据类型用于较小的浮点数,因为它要求的精度较低. double数据类型比 ...

  3. sicily 1198. Substring (递归全排列+排序)

    DescriptionDr lee cuts a string S into N pieces,s[1],…,s[N]. Now, Dr lee gives you these N sub-strin ...

  4. CCF CSP 201509-3 模板生成系统

    CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201509-3 模板生成系统 问题描述 成成最近在搭建一个网站,其中一些页面的部分内容来自数据 ...

  5. 转:springboot(二):web综合开发

    web开发 spring boot web开发非常的简单,其中包括常用的json输出.filters.property.log等 json 接口开发 在以前的spring 开发的时候需要我们提供jso ...

  6. 006 python的面向对象基础

    1.类 描述具有相同属性与方法的对象的集合. 2.创建类 使用class来创建一个新类,class之后为类的名称并以冒号结尾 3.程序 #!/usr/bin/python # -*- coding: ...

  7. Code First 数据库迁移

    当 Entity Framework Code First 的数据模型发生改变时,默认会引发一个System.InvalidOperationException 的异常.解决方法是使用DropCrea ...

  8. thinkphp 5.0 lnmp环境下 无法访问,报错500(public目录)

    两种方法: 1.修改fastcgi的配置文件 /usr/local/nginx/conf/fastcgi.conf fastcgi_param PHP_ADMIN_VALUE "open_b ...

  9. 【GO基础】神奇的iota特殊常量

    最近在学习GO语言,然后发现有一个特殊常量是以前没有接触过的,比较感兴趣,这里给大家介绍一下. iota,特殊常量,可以被认为是一个可以被编译器修改的常量. 核心概念:iota在const关键字出现时 ...

  10. Java 中的定时任务(一)

    定时任务简单来说就是在指定时间,指定的频率来执行一个方法,而在 Java 中我们又该如何实现呢? 想来主要有 3 种方式,最原始的方式肯定是开启一个线程,让它睡一会跑一次睡一会跑一次这也就达到了定频率 ...