浅谈C#依赖注入
什么是依赖注入?不管是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#依赖注入的更多相关文章
- 浅谈_依赖注入 asp.net core
1.1什么是依赖 我们先看下图 可以简单理解,一个HomeController类使用到了DBContext类,而这种关系是有偶然性,临时性,弱关系的,但是DBContext的变化会影响到HomeCon ...
- 浅谈(IOC)依赖注入与控制反转(DI)
前言:参考了百度文献和https://www.cnblogs.com/liuqifeng/p/11077592.html以及http://www.cnblogs.com/leoo2sk/archive ...
- 浅谈spring依赖注入
了解依赖注入 前言 先了解下控制反转--转自知乎的国哥 如果一个类A 的功能实现需要借助于类B,那么就称类B是类A的依赖,如果在类A的内部去实例化类B,那么两者之间会出现较高的耦合,一旦类B出现了问题 ...
- 浅谈WPF依赖项属性
浅谈WPF依赖项属性 0. 引言 依赖项属性虽然在使用上和CLR属性一样,但是它是WPF特有的,不同于CLR属性.只是封装为我们常用CLR的属性,在语法使用上和CLR属性一样.WPF中一些功能:动画, ...
- 以英雄联盟的方式建模,谈对依赖注入(DI)的理解以及Autofac的用法(一)
一.前言 近期在探索分层架构和架构设计,选择了领域驱动作为5年.Net开发后的新的方向,不可避免的接触了IoC/DI方面的技术.目前通过反射或其他方法都已实现,但只知其一,并没有考虑为什么要这么做,同 ...
- Spring5.0源码学习系列之浅谈循环依赖问题
前言介绍 附录:Spring源码学习专栏 在上一章的学习中,我们对Bean的创建有了一个粗略的了解,接着本文浅谈Spring循环依赖问题,这是一个面试比较常见的问题 1.什么是循环依赖? 所谓的循环依 ...
- 浅谈微信smali注入
作者:郭少雷 搞android搞了几年也没搞出个啥牛逼app出来,眼看时下最火的app微信如此火热,实在想搞搞它,索性就想着给它加点东西进去. 以下内容纯属本人个人爱好,仅限个人学习android用途 ...
- 谈谈php里的IOC控制反转,DI依赖注入
理论 发现问题 在深入细节之前,需要确保我们理解"IOC控制反转"和"DI依赖注入"是什么,能够解决什么问题,这些在维基百科中有非常清晰的说明. 控制反转(In ...
- 谈谈php里的IOC控制反转,DI依赖注入(转)
转自:http://www.cnblogs.com/qq120848369/p/6129483.html 发现问题 在深入细节之前,需要确保我们理解"IOC控制反转"和" ...
随机推荐
- [EXP]CVE-2018-2628 Weblogic GetShell Exploit
漏洞简介 漏洞威胁:RCE--远程代码执行 漏洞组件:weblogic 影响版本:10.3.6.0.12.1.3.0.12.2.1.2.12.2.1.3 代码: # -*- coding: utf-8 ...
- CSRF理解和实战
目录 啥是CSRF攻击 写一个CSRF攻击 如何避免CSRF攻击 啥是CSRF攻击 CSRF(Cross-site request forgery)跨站请求伪造,CSRF通过伪装来自受信任用户的请求来 ...
- Kafka实战-KafkaOffsetMonitor
1.概述 前面给大家介绍了Kafka的背景以及一些应用场景,并附带上演示了Kafka的简单示例.然后,在开发的过程当中,我们会发现一些问题,那就是消息的监控情况.虽然,在启动Kafka的相关服务后,我 ...
- C#效率优化(1)-- 使用泛型时避免装箱
本想接着上一篇详解泛型接着写一篇使用泛型时需要注意的一个性能问题,但是后来想着不如将之前的详解XX系列更正为现在的效率优化XX系列,记录在工作时遇到的一些性能优化的经验和技巧,如果有什么不足,还请大家 ...
- Linux下搭建DNS缓存服务器
CentOS 6.10搭建本地DNS缓存服务器系统环境 1 [root@test ~]# cat /etc/redhat-release 2 CentOS release 6.10 (Final) 3 ...
- [CF438E] 小朋友和二叉树
Description 给定一个整数集合 \(c\),对于每个 \(i\in[1,m]\),求有多少种不同的带点权的二叉树使得这棵树点权和为 \(i\) 并且顶点的点权全部在集合 \(c\) 中.\( ...
- soapui 自动化教程
本教程主要讲述对接口的自动化测试,略过压力测试.安全测试. 最终目标是通过groovy脚本执行一个文件,发送多个任务请求.验证返回值是否符合期望. 教程从soapui入门到groovy实现回传参数.生 ...
- break与continue,return结束循环区别
break是跳出一层循环,continue是结束一趟循环 ,return才是结束所有层循环! 如果有多层for循环,break会跳出当前这一层,去执行最外层循环(而不是退出所有层循环);而contin ...
- LINQ 【增、删、改、查】数据绑定
LINQ,语言集成查询(Language Integrated Query) 是一组用于c#和Visual Basic语言的扩展.它允许编写C#或者Visual Basic代码以查询数据库相同的方式操 ...
- RowVersion 用法
在数据表更新时,如何表征每个数据行更新时间的先后顺序?最简单的做法是使用RowVersion(行版本)字段,它和时间戳(TimeStamp)类型的功能相似,只不过TimeStamp 已过时,应避免用于 ...