zoukankan      html  css  js  c++  java
  • IOC详解和Unity基础使用介绍

    说起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 { get; set; }
           public iEat eat { get; set; }
           public iRun run { get; set; }
     
           [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

  • 相关阅读:
    递归回溯 UVa140 Bandwidth宽带
    嵌入式设备网络设置
    海思板卡SATA最佳读写块大小测试
    Linux日志轮循实现(shell)
    检测应用的内存泄漏情况(shell)
    Python的交叉编译移植至arm板
    写一个简单的配置文件和日志管理(shell)
    shell 实现主板测试
    主板硬件性能测试
    C语言 模2除法
  • 原文地址:https://www.cnblogs.com/android-blogs/p/6419786.html
Copyright © 2011-2022 走看看