C#摸鱼实录——IoC与DI案例详解

IoC(控制反转)与DI(依赖注入)


开一个新的模块哈,在这个模块里面,我们主要讲一个东西如何使用,尽量不纠结概念,简单过过

之前老是被人说,是不是过于偏向于学院派了,所以从现在开始,我们将只关注能不能用

这个模块里面,我想讲的,大多数是在实际项目中常用的东西,例如一些NuGet 包,一个语法,或者某种设计模式
不过不过多描述概念了,不讲官方那些罗里吧嗦的概念,只需要理解他是什么鬼东西,干什么的,怎么用即可
大抵就是学院派和江湖派的区别吧

顺便后面我要是忘记这个东西怎么用了,还可以回来看看文档,顺便,这就是我未来AI的蒸馏对象我蒸馏我自己

然后,为什么要进行这么古老的学习方式,废话,这年头AI快把初级员工的路堵死了,
不来点古法编程,抽象能力提升很慢的,用了AI几个月,发现初级迈向中级,你不古法编程就等死吧
而且上班摸鱼时间一大把,系统性的学习学习怎么了,打发时间也挺好的,然后深入学习一下IoC的思想

废话少说,进入正题


一.DI依赖注入 — 概念

[!TIP]

如果你不想看文字,或者觉得我这一块讲的不是特别明白的,想看视频教学的话
推荐一位up做的关于依赖注入的教学视频,大概30分钟左右的教学,
只不过后面几个视频初学者容易看不懂
【.Net-依赖注入】从依赖说起_哔哩哔哩_bilibili

很多人可能经常使用依赖注入,但是不知道他叫什么,DI是什么鬼东西,其实看一眼代码就了解了不懂你就再看一眼


1.什么是依赖(Dependency)?

  • 一个对象要工作,需要另一个对象的帮助,没有另一个对象就完成不了

  • /// 因为产品需要零件A,所以产品依赖于零件A /// 即:零件A就是产品的依赖 public class 零件A { public int GetID() => 100; } public class 产品 { private readonly 零件A _a; public 产品(零件A a) => _a = a; }

2.什么是注入(Injection)?

  • 把对象交给另一个对象使用

    • // 通过对象product使用了对象a var a = new 零件A(); var product = new 产品(a);

3.什么是依赖注入(Dependency Injection)?

  • 依赖注入 = 依赖 + 注入

    • 即:对象所需要的依赖由外部提供,而不是自己创建
  • 下面是依赖注入的一点基本概念,结合上面的内容,已经写的非常清楚了,就不再过多阐述

  • // 一个用于示例的空类DbService public interface IDbService { void Insert(); } public class DbService : IDbService { public DbService() { } public void Insert() => Console.WriteLine("====================================="); } /// <summary> /// 传统写法 - 不使用依赖注入(模块之间强依赖,耦合度高) /// </summary> public class NO_DI { // 🌱钱没给够,你自己new吧 private DbService _db = new DbService(); public void Save() => _db.Insert(); } /// <summary> /// 使用依赖注入(松散解耦) /// </summary> public class Yes_DI { private readonly DbService _db; // 🌱钱给够了,直接从外部“注入” public Yes_DI(DbService db) => _db = db; public void Save() => _db.Insert(); } /// <summary> /// 依赖注入常用三种方式(但是基本上还是以构造注入为主) /// </summary> /// <summary> /// 1.1构造注入 /// </summary> public class 构造注入 { private readonly DbService _db; public 构造注入(DbService db) => _db = db; // var a = new A(); // var demo = new 构造注入(a); } /// <summary> /// 1.2.属性注入 /// </summary> public class 属性注入 { public 属性注入() { } public DbService DB { get; set; } = null!; // 属性注入 demo = new 属性注入(); // demo.DB = new DbService(); } /// <summary> /// 1.3.方法注入 /// </summary> public class 方法注入 { public 方法注入() { } public void Execute(DbService db) { } // 方法注入.Execute(new DbService()); }

二.IoC(控制反转)— 概念

1.什么是控制(Control)?

  • 谁决定对象如何产生和使用

    • 控制权:决定某件事情如何进行的权力
      • 在IoC中,特指:创建什么对象,什么时候创建,对象如何创建对象的决定权
      • 看不懂就看下面的例子,一眼秒懂
  • // 产品控制着零件A的创建 // 即:产品拥有创建零件A的控制权 // 缺点,产品和零件A已经绑死了,高度耦合,扩展等死,后人挠头,直骂屎山 public class 零件A { } public class 产品 { private readonly 零件A _a; public 产品() { _a = new 零件A(); } }

2.什么是反转(Inversion)?

  • 反转 = 原来的方向反过来了

    • 原本由A负责的事情,改由B负责
  • 在IoC中通常指:控制权发生变化,由内部控制变成外部控制

  • public class 零件A { } //======================================= // 内部控制 public class 产品 { private readonly 零件A _a; public 产品() { _a = new 零件A(); } } //======================================= // 外部控制 public class 产品 { private readonly 零件A _a; public 产品(零件A a) { _a = a; } }

3.什么是控制反转(Inversion of Control)?

  • 控制方向被反过来了,所以叫控制反转

  • 控制反转:原本由对象自己掌握的控制权,转移给了外部对象或容器

    • 但是需要注意的是,IoC是一种思想,它并不是某种具体的实现
    • 换句话说,DI是IoC的一种实现方式,依赖注入就是使用控制反转的思想
      • 即:依赖注入(DI)是实现IoC最常见的方式之一
  • # 原来:产品内部控制零件A 产品 ↓ # 控制 零件A #==================================================