之前就听同事说过依赖注入(dependency injection)、控制反转(Inversion of Control)。起初听的是一头雾水,试着在项目中运用了几次,总算明白了一些,抛砖引玉,与大家分享一下拙见。

其实依赖注入和控制反转指的都是同一个事情。什么是依赖注入了???

【个人理解】

以最熟悉的三层架构的项目来说,BLL层依赖DAL层,UI层依赖于BLL层,层层之间紧密联系。代码里到处都是new 对象。认识IOC后,发现IOC最大的好处就是解耦了对这种层级之间的依赖关系进。程序本身不在负责对象的创建和维护,而交给外部容器(IOC容器)来负责。外部容器在运行时动态地将依赖的对象注入到组件之中。

简单的来说就是在类型A中需要使用类型B的实例,而B实例的创建并不由A来负责,而是通过外部容器来创建。相比以往实例化对象的写法,确实很爽。

以往实例化都是这样的:

public class A
{public A(B b){this.B = b;}public B B { get; set; }public void Test(B b){Console.WriteLine(b.ToString());}
}

A 类受B类的影响很大。A类的构造函数中,实例化B,且在A类的Test的方法中,需要判断B类是不是被实例化。A即创建B又需要维护B。用了IOC,解耦了这种依赖关系。接下来看看我在项目中是怎么简单应用的。

【项目简单试用】

一开始用的IOC容器是Unity,四个字,短小精干(用了有段日子。还有好多功能还需不断去探索) 。网上还有其它的IOC容器,没有去了解过(个人认为,能把一个工具用会,用熟,用精,才是王道。)

我把项目中的一段代码摘出来,项目需求大致上是项目有个数据统计,它下面有三种不同的统计类型,需要与数据库交互,然后展示到页面。

首先需要Unity的类库,利用VS2012的库程序包管理工具去下载Unity的类库。

项目的结构是这样,标准的是三层架构,BLL和DAL都有接口层IBLL,IDAL。

首先我们按照不用IOC的方式来实现这个小需求。

IDAL,IBLL 创建接口 IAnalyse 接口里有个方法

public interface IAnalyse{/// <summary>/// 显示结果/// </summary>void ShowResult();}

DAL 层引用IDAL,创建类 Analyse.cs

public class Analyse:IDAL.IAnalyse { public void ShowResult() { Console.WriteLine("分析底层数据库交互"); } }

BLL层引用IDAL,DAL,IBLL 创建 类 Analyse.cs

      /// <summary>/// 显示结果/// </summary>public void ShowResult(){////以前思路 需要引用IBLL,IDAL,DALIDAL.IAnalyse dal = new DAL.Analyse();dal.ShowResult();}

UI层用控制台应用程序来代替。需引用IBLL,BLL

class Program{static void Main(string[] args){OldMethod();Console.ReadKey();}/// <summary>/// 在使用IOC前的写法。需要引入IBLL,BLL/// </summary>static void OldMethod(){IBLL.IAnalyse bll = new BLL.Analyse();bll.ShowResult(); }}

按照以前的方法,每个层我们都在不断的new 对象。写到这里发现这些都是很中规中矩的写法,以前老师教的也是这样,可能你会觉得没啥不好的。我就假如:BLL.Analyse 的构造函数需要参数,参数为Class B ,去掉无参的构造函数,你是不是所有new 对象的地方都要更改。小项目也许还没有问题,如果是上百万的大项目咋办。这就是所谓的层与层之间的耦合度高。(个人拙见,多多指教)

接下来我们用 IOC 来解耦。在Program.cs 增加 IOCMethod1 方法

static void Main(string[] args){//OldMethod();
            IOCMethod1();Console.ReadKey();}static void IOCMethod1(){IUnityContainer container=new UnityContainer();////在容器中注册一种类型,它是一个类型的映射,接口类型是IAnalyse,希望返回的类型是Analysecontainer.RegisterType<IBLL.IAnalyse, BLL.Analyse>();////第二种写法//container.RegisterType(typeof (IBLL.IAnalyse), typeof (BLL.Analyse));IBLL.IAnalyse bll = container.Resolve<IBLL.IAnalyse>();bll.ShowResult();}

使用unity就三步:

第一,new IOC 容器

第二,调用RegisterType 注册类型。这里有多种注册形式。可以注册单例的、构造函数有参数的。

第三,调用Resolve 创建对象

(认识IOC 简单吧 O(∩_∩)O)

到这,你会发现,UI层 仍然引用了IBLL,BLL,RegisterType方法需要这两个类库。既然是解耦,就得解耦彻底些。有什么方法???

我在Core层 DependencyRegister.cs. 建立一个静态方法,在程序运行开始的时候,注册所有的类型。UI 层移除BLL ,引用Core

namespace Core
{/// <summary>/// 类型注册/// </summary>public class DependencyRegister{public static IUnityContainer DependencyRegisterContainer(){IUnityContainer container = new UnityContainer();container.RegisterType<IBLL.IAnalyse, BLL.Analyse>().RegisterType<IDAL.IAnalyse, DAL.Analyse>();return container;}}
}////UI层 先移除BLL,引用Core
static void Main(string[] args){IOCMethod2();Console.ReadKey();}static void IOCMethod2(){  IUnityContainer container = DependencyRegister.DependencyRegisterContainer();
IBLL.IAnalyse bll = container.Resolve<IBLL.IAnalyse>();  bll.ShowResult();      }

这样达到了解耦的目标,如何需要更改类的构造函数,只需更改Core DependencyRegister.cs 就可以了。

【其它解耦方式】

建立core是用了自己得方法来实现解耦的,其实unity还有更觉得,通过配置文件 app.config 来实现。用的是 Microsoft.Practices.Unity.Configuration.dll

    <!-- 程序集--><assembly name="IBLL"/><assembly name="IDAL"/><!--要返回的类型--><alias alias="BLLAnalyse1" type="BLL.Analyse, BLL" /><container name="ContainerAnalyse"><register type="IBLL.IAnalyse" name="BLLAnalyse1" mapTo="BLLAnalyse1" /></container>

private static void IOCMethod3(){////通过配置文件注册所有类型IUnityContainer container=new UnityContainer();UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");section.Configure(container, "ContainerAnalyse");IBLL.IAnalyse bll = container.Resolve<IBLL.IAnalyse>("BLLAnalyse1");bll.ShowResult();}

【投机取巧】

无论是使用全局方法,或者 配置文件,都是注册类的形式不同。每种方法都需要调用Resolve 来创建对象。有没有连改方法都不用调用的形式。

不用多说,直接上代码:

namespace BLL
{public class Analyse:IBLL.IAnalyse{////使用依赖注入
        [Dependency]public IDAL.IAnalyse dal { get; set; }/// <summary>/// 显示结果/// </summary>public void ShowResult(){////以前思路 需要引用IBLL,IDAL,DAL//IDAL.IAnalyse dal = new DAL.Analyse();
            dal.ShowResult();}}
}

使用[Dependency]属性。说实话,它的用法还有些没有弄明白。希望明白这个得多指教指教。

献丑了,有什么不对的地方希望大家多多指教。Unity 功能很多,这篇只不过是凤毛麟角,还有什么构造注入,属性注入、单例的应用。这些,将在下篇继续分享。希望大家继续关注,多多指教。

转载于:https://www.cnblogs.com/jameslif/p/3542495.html

我在项目中运用 IOC(依赖注入)--入门篇相关推荐

  1. Lind.DDD.IoC依赖注入与面向方面的实现

    IoC是解耦的灵魂,很难想像一个框架中没有IoC会变成什么样子,Lind.DDD里的IoC是通过Unity实现的,由依赖注入(unity)和方法拦截组成(Interception),依赖注入可以通过事 ...

  2. 关于mysql注入说法正确的是_1. 在 Spring中,下列关于 依赖注入 的 说法 , 正确的是( ) 。_学小易找答案...

    [简答题]1基本流程练习 2时间轴嵌套 3简单应用 [简答题]请解释什么是MVC? [多选题]在 Hibernate 中,下 列 说法正确的有 [多选题]1. 关于 Spring,下列说法不正确的是( ...

  3. 管理java版本号_微服务项目中如何管理依赖版本号?

    本文是微服务项目代码组织形式三部曲中的第三篇,也是最后一篇,通过这三篇文章,相信大家对于如果组织微服务中的代码已经有了一个基本认知,前面两篇分别是: 微服务项目搭建,到底要不要聚合工程? 在微服务项目 ...

  4. Android:dagger2让你爱不释手-基础依赖注入框架篇

    前言 dagger2的大名我想大家都已经很熟了,它是解决Android或java中依赖注入的一个类库(DI类库).当我看到一些开源的项目在使用dagger2时,我也有种匆匆欲动的感觉,因此就立马想一探 ...

  5. Spring DI(依赖注入)注解篇

    1 课程内容介绍 我之前写的的一篇博客Spring核心功能DI(依赖注入)xml篇主要介绍了如何通过配置xml的方式来实现依赖注入,今天我们来介绍如何通过注解方式完成我们的依赖注入操作. 2 注入基本 ...

  6. 从真实项目中抠出来的设计模式——第二篇:过滤器模式

    一:实际场景介绍 我们在给用户做订单催付通知的时候,会有这样的一种场景,用户在系统后台设置一组可以催付的规则,比如说订单金额大于xx元,非黑名单用户,来自 哪个地区,已购买过某个商品,指定某个营销活动 ...

  7. .NET Core实战项目之CMS 第六章 入门篇-Vue的快速入门及其使用

    写在前面 上面文章我给大家介绍了Dapper这个ORM框架的简单使用,大伙会用了嘛!本来今天这篇文章是要讲Vue的快速入门的,原因是想在后面的文章中使用Vue进行这个CMS系统的后台管理界面的实现.但 ...

  8. .NET Core实战项目之CMS 第五章 入门篇-Dapper的快速入门看这篇就够了

    写在前面 上篇文章我们讲了如在在实际项目开发中使用Git来进行代码的版本控制,当然介绍的都是比较常用的功能.今天我再带着大家一起熟悉下一个ORM框架Dapper,实例代码的演示编写完成后我会通过Git ...

  9. .NET Core实战项目之CMS 第四章 入门篇-Git的快速入门及实战演练

    写在前面 上篇文章.NET Core实战项目之CMS 第三章 入门篇-源码解析配置文件及依赖注入我带着大家通过分析了一遍ASP.NET Core的源码了解了它的启动过程,然后又带着大家熟悉了一遍配置文 ...

  10. RequireJS代码文件依赖管理 - 入门篇

    使用RequireJS库,进行代码文件依赖管理 一.关键字 存在依赖.手动线性方式管理文件之间的依赖.潜在关联性 二.了解 require.js 库 简单介绍: require.js 是一款JavaS ...

最新文章

  1. [JS][dp]题解 | #打家劫舍(一)#
  2. 中文版GPT-3来了?智源研究院发布清源 CPM —— 以中文为核心的大规模预训练模型...
  3. 零基础Java学习之类和对象
  4. 微信小程序扫二维码折中进入体验版
  5. 单例设计模式八种方式——5) 懒汉式(线程安全,同步代码块) 6) 双重检查 7) 静态内部类 8) 枚举
  6. 引路蜂地图API:Drawing包定义
  7. python 对象序列化 pickling_[Python]对dat文件的操作:序列化对象
  8. 链表之反转部分单向链表
  9. [恢]hdu 1019
  10. python计算两个数的最大公约数和最小公倍数
  11. sublime java 编译_03 sublime text3下配置Java的编译运行环境
  12. vs2003不能调试4/8
  13. setImageResource导致的ANR
  14. python数字猜大小游戏
  15. matlab中适应度函数怎么编写,matlab常用的几个适应度评价函数
  16. SAP GUI登陆系统报Validity of certificate from list with PSE type >SSL错误弹窗
  17. 30条爆笑的程序员梗PHP是最好的语言
  18. thinkpad E450/550 预装系统改装WIN7全套教程
  19. 2022外卖霸王餐程序、外系统霸王餐H5/APP程序源码|美团/饿了么霸王餐系统 粉丝裂变 自带账单 在线支付提现等
  20. MPP(大规模并行处理)

热门文章

  1. 倒置链表(递归方式)
  2. mysql 防火墙 centos_CentOS 开启防火墙 firewall ,mysql 远程访问
  3. qt 日历类 不可输入当前日期之后的日期_UI设计组件时间选择器,日历设计从未如此简单!...
  4. MVCC常问面试题(面试重点)
  5. 关于2020新版idea,maven工程依赖成功导入、但运行找不到jar包问题解决。
  6. Java基础:常用的API
  7. 实战Swiper:利用Swiper制作手机新闻界面
  8. Javascript特效:一个不停的表盘
  9. Java中的几种设计模式:创建型模式,结构型模式
  10. 论文笔记_S2D.47_2017-ICRA_SemanticFusion(语义融合):采用卷积神经网络CNN的稠密3D语义建图