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
    #==================================================
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐