什么是依赖注入?不管是js中的一些前端框架还是,java,C#等中的一些后端语言开发框架中,都会涉及这个的词语:依赖注入,单纯听这个词汇好像很厉害的样子,大部分人都会对未知的事物产生排斥和畏惧,但是其实只要通过简单学习后你会发现其实并没有想象中那么复杂。

1,基本概念

依赖注入?控制反转?

  依赖注入控制反转的一种具体实现方式,那什么又是控制反转:它是面向对象编程中的一种设计原则,其作用主要用来减低计算机代码之间的耦合度,

  其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体,将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。

2,概念理解与运用

如果有一定的面向对象思想其实要理解这一概念的并不算太难,我们常规面向对象最基本的思想就是我们会把某些业务模块需要封装成为一个类,然后在需要的地方去实例化调用,我们不妨举一个生活中的简单栗子,把它体现到代码之中后,看看代码不使用依赖注入和使用依赖注入有什么区别:

如果把我自己比作一个类,假定我这个类里面有工作“Work()”和休息放假“Holiday()”两个函数,然后我在工作和休息两个函数中都会用到我的苹果手机,工作“Work()”函数中会用手机打电话和发邮件,休息“Holiday()”函数会用手机玩游戏、上网还有看视频,我们把手机也看成另一个类,手机类分别实现了:打电话:Call()、发邮件:Eamil()、玩游戏:PlayGame()、上网:Internet()、看视频:VideoPlay()五个函数。代码如下:

    public class Person
{ }
public class Me : Person
{
public void Work()
{
//…… 省略若干代码
iphone phone = new iphone();
phone.Call();
phone.Eamil();
} public void Holiday()
{
//…… 省略若干代码
iphone phone = new iphone();
phone.PlayGame();
phone.VideoPlay();
phone.Internet();
}
} public class iphone
{
public void Call()
{
//…… 省略若干代码
Console.WriteLine($"iphone手机打电话");
} public void Eamil()
{
//…… 省略若干代码
Console.WriteLine($"iphone手机发送邮件");
} public void PlayGame()
{
//…… 省略若干代码
Console.WriteLine($"iphone手机玩游戏");
} public void VideoPlay()
{
//…… 省略若干代码
Console.WriteLine($"iphone手机播放视频");
} public void Internet()
{
//…… 省略若干代码
Console.WriteLine($"iphone手机上网");
}
}

调用代码:

    public class Program
{
public static void Main(string[] args)
{
int[] Holiday = { , };
//获取当前时间
DateTime time = DateTime.Now;
//实例化Me对象
Me me = new Me(); if (Holiday.Contains((int)time.DayOfWeek))
{
//如果当前时间为周六,周日,执行Holiday
me.Holiday();
}
else
{
//如果当前时间不为周六,周日,执行Work
me.Work();
}
}
}

看到这个代码我们觉得很OK,终于可以愉快的工作和休息了,但是好景不长,有一天我从苹果手机换成了华为手机,为了我代码可以正常运行,我必须把所有实例化过iphone类的地方改成实例化华为类,在将来我每换一次手机,我的对应的实例也会跟着改变,代码实例对象的地方存在耦合。所以我们要想办法解耦,怎么处理呢?

    public class Person
{ }
public class Me : Person
{
private phone myphone; public Me(phone _phone)
{
myphone = _phone;
} public void Work()
{
//…… 省略若干代码
myphone.Call();
myphone.Eamil();
} public void Holiday()
{
//…… 省略若干代码
myphone.PlayGame();
myphone.VideoPlay();
myphone.Internet();
}
}
public abstract class phone
{
public abstract void Call();
public abstract void Eamil();
public abstract void PlayGame();
public abstract void Internet();
public abstract void VideoPlay();
} public class iphone : phone
{
public override void Call()
{
//…… 省略若干代码
Console.WriteLine($"iphone手机打电话");
} public override void Eamil()
{
//…… 省略若干代码
Console.WriteLine($"iphone手机发送邮件");
} public override void PlayGame()
{
//…… 省略若干代码
Console.WriteLine($"iphone手机玩游戏");
} public override void VideoPlay()
{
//…… 省略若干代码
Console.WriteLine($"iphone手机播放视频");
} public override void Internet()
{
//…… 省略若干代码
Console.WriteLine($"iphone手机上网");
}
} public class huaweiphone : phone
{
public override void Call()
{
//…… 省略若干代码
Console.WriteLine($"华为手机打电话");
} public override void Eamil()
{
//…… 省略若干代码
Console.WriteLine($"华为手机发送邮件");
} public override void PlayGame()
{
//…… 省略若干代码
Console.WriteLine($"华为手机玩游戏");
} public override void VideoPlay()
{
//…… 省略若干代码
Console.WriteLine($"华为手机播放视频");
} public override void Internet()
{
//…… 省略若干代码
Console.WriteLine($"华为手机上网");
}
}

代码标红的地方是主要涉及依赖注入的地方,我们把手机类作为一个父类,然后华为和iPhone都继承此类,然后我们把手机类作为Me类的成员,这样改动后我们的调用代码如下

     public class Program
{
public static void Main(string[] args)
{
int[] Holiday = { , };
//获取当前时间
DateTime time = DateTime.Now;
//实例化手机对象
phone phone = new huaweiphone();
//实例化Me对象
Me me = new Me(phone); if (Holiday.Contains((int)time.DayOfWeek))
{
//如果当前时间为周六,周日,执行Holiday
me.Holiday();
}
else
{
//如果当前时间不为周六,周日,执行Work
me.Work();
}
}
}

代码这样更改之后不管我们要用iPhone类还是华为类还是其他新的手机类去实现我们的Holiday()和Work()中的函数,我们不需要对Me类做任何改动,只需要去改变传输的对象,在调用时灵活的将我们所需要的依赖对象注入到Me类之中,这就就是传说中的依赖注入。

回看前面的例子再用我自己的话来理解依赖注入:就是把依赖部分(代码不可控或者经常变动的耦合的部分)变成一个抽象的成员(类、抽象类或接口),然后根据具体所需要的实例去灵活的注入依赖,来达到控制反转的效果,从而实现代码解耦。

上面这个简单的例子中依赖部分就是iPhone类,华为类这种可能存在变动的类,每种手机具体实现打电话Call(),发邮件Eamil()等功能的方式可能都有差异,我们只能在具体要用到的时候才会知道到底要用哪一种手机,所以在具体调用的时候去注入手机对象是相对灵活而且耦合度低的一种方案。

3,C#常用的依赖注入方式

  1,通过构造器进行依赖注入

  2,通过属性的访问器进行依赖注入

  3,通过接口实现依赖注入

  4,通过反射,特性也可以实现依赖注入

我们上面例子是通过构造函数实现的简单的依赖注入,其他几种方式在搞清楚代码基础语法概率之后其实也都差不多,我就不一一举例了,不管用什么方式实现依赖注入,理解其中的基本思想是最重要的。

浅谈C#依赖注入的更多相关文章

  1. 浅谈_依赖注入 asp.net core

    1.1什么是依赖 我们先看下图 可以简单理解,一个HomeController类使用到了DBContext类,而这种关系是有偶然性,临时性,弱关系的,但是DBContext的变化会影响到HomeCon ...

  2. 浅谈(IOC)依赖注入与控制反转(DI)

    前言:参考了百度文献和https://www.cnblogs.com/liuqifeng/p/11077592.html以及http://www.cnblogs.com/leoo2sk/archive ...

  3. 浅谈spring依赖注入

    了解依赖注入 前言 先了解下控制反转--转自知乎的国哥 如果一个类A 的功能实现需要借助于类B,那么就称类B是类A的依赖,如果在类A的内部去实例化类B,那么两者之间会出现较高的耦合,一旦类B出现了问题 ...

  4. 浅谈WPF依赖项属性

    浅谈WPF依赖项属性 0. 引言 依赖项属性虽然在使用上和CLR属性一样,但是它是WPF特有的,不同于CLR属性.只是封装为我们常用CLR的属性,在语法使用上和CLR属性一样.WPF中一些功能:动画, ...

  5. 以英雄联盟的方式建模,谈对依赖注入(DI)的理解以及Autofac的用法(一)

    一.前言 近期在探索分层架构和架构设计,选择了领域驱动作为5年.Net开发后的新的方向,不可避免的接触了IoC/DI方面的技术.目前通过反射或其他方法都已实现,但只知其一,并没有考虑为什么要这么做,同 ...

  6. Spring5.0源码学习系列之浅谈循环依赖问题

    前言介绍 附录:Spring源码学习专栏 在上一章的学习中,我们对Bean的创建有了一个粗略的了解,接着本文浅谈Spring循环依赖问题,这是一个面试比较常见的问题 1.什么是循环依赖? 所谓的循环依 ...

  7. 浅谈微信smali注入

    作者:郭少雷 搞android搞了几年也没搞出个啥牛逼app出来,眼看时下最火的app微信如此火热,实在想搞搞它,索性就想着给它加点东西进去. 以下内容纯属本人个人爱好,仅限个人学习android用途 ...

  8. 谈谈php里的IOC控制反转,DI依赖注入

    理论 发现问题 在深入细节之前,需要确保我们理解"IOC控制反转"和"DI依赖注入"是什么,能够解决什么问题,这些在维基百科中有非常清晰的说明. 控制反转(In ...

  9. 谈谈php里的IOC控制反转,DI依赖注入(转)

    转自:http://www.cnblogs.com/qq120848369/p/6129483.html 发现问题 在深入细节之前,需要确保我们理解"IOC控制反转"和" ...

随机推荐

  1. Hadoop社区版搭建

    1.环境准备 1.1 硬件配置 设备名 参数 数量 6台 系统 centos6.5 内存 64G 硬盘 32T/台 CPU 16核/台 1.2 软件版本 Hadoop-2.x 下载地址 JDK1.7  ...

  2. leetcode — integer-to-roman

    /** * Source : https://oj.leetcode.com/problems/integer-to-roman/ * * Created by lverpeng on 2017/7/ ...

  3. 进程间通信IPC-信号量

    semget  semget函数创建一个新的信号量或是获得一个已存在的信号量键值. int semget(key_t key, int num_sems, int sem_flags); 第一个参数k ...

  4. #17 random&json模块

    前言 本节将讲解两个模块,一个是随机模块random,一个是字符串和字典之间的转换模块json,这两个模块使用率还是很高的,来认识一下! 一.random模块 random的官方文档:https:// ...

  5. .13-浅析webpack源码之WatcherManager模块

    从模块流可以看出,这个NodeWatchFileSystem模块非常深,这里暂时不会深入到chokidar模块,有点太偏离本系列文章了,从WatcherManager开始讲解. 流程如图: 源码非常简 ...

  6. 图解Docker容器和镜像

    图解Docker容器和镜像 这篇文章希望能够帮助读者深入理解Docker的命令,还有容器(container)和镜像(image)之间的区别,并深入探讨容器和运行中的容器之间的区别. 当我对Docke ...

  7. .NET实现发送邮件

    注意:需要找到“POP3/SMTP服务”并开启,然后生成授权码,生成的授权码就是下面登入的密码. /// <summary> /// 发送邮件 /// </summary> / ...

  8. response slider

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <t ...

  9. [js高手之路]深入浅出webpack教程系列2-配置文件webpack.config.js详解(上)

    [js高手之路]深入浅出webpack教程系列索引目录: [js高手之路]深入浅出webpack教程系列1-安装与基本打包用法和命令参数 [js高手之路]深入浅出webpack教程系列2-配置文件we ...

  10. 网络编程学习二(IP与端口)

    InetAddress类 封装计算机的ip地址,没有端口 // 使用getLocalHost方法创建InetAddress对象 InetAddress addr = InetAddress.getLo ...