• ASP.NET没有魔法——ASP.NET MVC IoC


      之前的文章介绍了MVC如何通过ControllerFactory及ControllerActivator创建Controller,而Controller又是如何通过ControllerBase这个模板完成了功能的拓展及业务的执行。这一系列MVC类型的设计处处都体现了IoC的设计原则,所以本章将从以下几点对ASP.NET MVC中的IoC进行介绍:
      ● 什么是IoC
      ● ASP.NET MVC中的IoC
      ● 什么是DI
      ● IoC容器与依赖解析器(Dependency Resolver)
      ● ASP.NET MVC中使用DI

    什么是IoC

      IoC(控制反转,Inversion of Control)它是软件开发中的一种设计原则,意思就是把控制权从自身(这里的自身大部分指代的是业务代码)转给其它对象来控制。IoC的意图是将任务的执行从实现中解耦,可以专注于模块任务的设计(如:操作数据库的组件,可以有操作SQL Server和My SQL的),系统本身不会关注这个模块做了什么,同时当系统替换了这个模块后不会对系统造成影响。在软件开发中有几种常见的基于IoC思想的实现:
      ● 工厂模式
      ● 模板模式
      ● 策略模式
      ● 依赖注入

      以上模式都是将实现解耦,便于拓展。特别是依赖注入(DI,Dependency Injection),看到IoC更多想到的就依赖注入。
      依赖倒置原则(DIP):上面说了那么多的实现,但有一个根本的原则就是依赖倒置原则“高层模块不依赖于低层模块,它们都应该依赖于抽象,抽象不应该依赖于实现,实现应该依赖于抽象”。在.Net中就是使用接口和抽象类对业务和对象进行抽象,抽象与实现分开,如果放弃了这一原则实现依赖于实现,那么就反转不了了(lll¬ω¬)。

    ASP.NET MVC中的IoC

      之前的文章中分析了ASP.NET MVC中Controller的创建过程和执行中主要的参与对象分别有:
      ● DefaultControllerFactory:工厂模式。
      ● DefaultControllerActivator:依赖注入(注:创建Controller时首先从依赖解析器中获取Controller实例,无法获取才自己创建)。
      ● ControllerBase:模板模式(注:ControllerBase定义了Execute模板方法调用抽象方法ExecuteCore,ExecuteCore的实现在子类中)。

      这些对象的设计思想就是IoC。

    什么是DI

      DI(Dependency Injection,依赖注入),它其实是两个部分,第一个是“依赖”,然后才是“注入”。
      1. 依赖:简单来说就是需要,在面向对象的一个类里面它“需要”其它类型来完成工作。如在MyBlog中的逻辑类需要仓储类来操作数据库,这种情况下就是逻辑类依赖仓储类:

       

      2. 注入:其实就是对类的依赖赋值,常用的注入的方式是:构造注入、属性注入、方法注入,说白了就是通过构造方法、属性(Setter方法)以及方法将依赖的对象传入类的实例中并赋值。但要注意的是这个“注”字,为什么不直接用赋值?
      举个栗子:制作一个水球,要么留一个注水口,要么在制作的时候把水灌入然后封死。
      对于有注水口的水球,在使用时如果注入红色的水,就变成了红色的水球,注入黄色的就是黄色的,而被封死的水球在制作时灌了什么颜色的水就是什么颜色的。
      而在程序开发中更是如此,以MyBlog为例,业务逻辑类通过仓储类来获取数据,业务类可以“封死”只用SQL Server的操作类,也可以开放,在运行时将数据操作这个实例“注入”,那么注入SQL Server操作类就使用SQL Server,注入MySQL的就使用My SQL。
      对水球注水首先要有水,其次是水球要有注水口,那么在程序里的“水”和“注水口”是什么?

    IoC容器与依赖解析器(DependencyResolver)

      在程序中所谓的“水”应该是那些抽象的实现,或者说实现了抽象的类型。比如操作SQL Server的仓储类和操作MySQL的仓储操作类。那么这些“水”要放在哪里?“水”当然要放在容器里,所以就有了IoC容器。
      那IoC容器是什么?它可以简单到只是一个实例的数组或字典,通过实例的类型(或实现的父类型、接口等)从这个字典或数组中获取对应的实例,也可以是像Autofac、Ninject这些复杂成熟的IoC容器组件。
      以下代码分别是AutoFac和NinJect官方文档中为容器注“水”的过程:
      Ninject:https://github.com/ninject/ninject

      

      AutoFac:https://autofac.org/

      

      有了装满“水”的容器,想要把“水”注入到程序中,那就需要“注水口”依赖解析器(Denpendency Resolver)的支持。
      以下代码就是DefaultControllerActivator创建Controller的代码:

      

      想象一下,把上面的“注水口”连接到装满“水”的容器中,不是就能够把需要的东西注入到需要的位置吗?

    ASP.NET MVC中使用DI

      DI的使用有两个必要条件就依赖容器依赖解析器,ASP.NET中建议使用成熟的依赖容器,如Autofac等,它们提供了强大的功能并支持多种组件注册到容器以及注入方式。而关于依赖解析器在ASP.NET MVC中是有默认解析器的,以下是ASP.NET MVC的解析器定义:

      

      它实际的作用是通过Current属性获取一个IDependencyResolver的对象。
      DependencyResolver中内置了一些实现该接口的对象,但是几乎是无用的如下图:

      

      所以一般情况下如果在ASP.NET中都是实现IDependencyResolver接口然后通过DependencyResolver.SetResolver方法修改默认的依赖解析器

      在ASP.NET MVC中,使用依赖注入最频繁的就是Controller,Controller作为业务逻辑执行的入口,它依赖业务逻辑的组件,而业务逻辑组件又依赖数据操作组件等等。所以在ASP.NET MVC中使用依赖注入实际上就是把Controller及其依赖都放入容器里,然后创建Controller时从容器中获取即可。根据Controller的创建流程将使用方法分为以下几种:
      1. 实现IDependencyResolver接口然后通过DependencyResolver.SetResolver方法修改默认的依赖解析器(替换默认的“注水口”)。
      2. 实现IControllerActivator接口,然后在创建DefaultControllerFactory时将其以参数的形式传入到DefaultControllerFactory中(在ControllerActivator中添加自己的“注水口”,并替换掉原有的ControllerActivator)。
      3. 继承DefaultControllerFactory使用从容器中获取Controller的方法将原有的GetControllerInstance方法替换掉(添加“注水口”放置在ControllerFactory中,放弃ControllerActivator的使用)。

      注:由于在Controller类型中包含一个IDependencyResolver属性,所以方法2和方法3没有替换默认依赖解析器会导致Controller中使用该属性无法访问到真实的容器,如果需要在其基础上使用方法1将默认的依赖解析器替换掉。

    小结

      IoC容器和依赖注入在软件开发中是一个非常中要的概念,现在主流的一些开发框架的核心都是基于依赖注入的,即框架中的所有组件如日志、缓存、队列等都会通过容器将其注入到使用的地方。本章主要以文字的形式介绍了IoC、DI的概念及其在ASP.NET MVC中的使用的三种方法,在下一篇文章中将会用代码的形式介绍如何使用这三种方法在ASP.NET MVC中实现依赖注入。

    参考:

      https://en.wikipedia.org/wiki/Inversion_of_control

    本文连接:http://www.cnblogs.com/selimsong/p/7682808.html 

    ASP.NET没有魔法——目录

    ASP.NET没有魔法——ASP.NET MVC IoC代码篇

  • 相关阅读:
    对象池使用时要注意几点
    Flash3D学习计划(一)——3D渲染的一般管线流程
    714. Best Time to Buy and Sell Stock with Transaction Fee
    712. Minimum ASCII Delete Sum for Two Strings
    647. Palindromic Substrings(马拉车算法)
    413. Arithmetic Slices
    877. Stone Game
    338. Counting Bits
    303. Range Sum Query
    198. House Robber
  • 原文地址:https://www.cnblogs.com/selimsong/p/7682808.html
Copyright © 2020-2023  润新知