IOC控制反转

大部分应用程序都是这样编写的:编译时依赖关系顺着运行时执行的方向流动,从而生成一个直接依赖项关系图。 也就是说,如果类 A 调用类 B 的方法,类 B 调用 C 类的方法,则在编译时,类 A 将取决于类 B,而 B 类又取决于类 C

应用程序中的依赖关系方向应该是抽象的方向,而不是实现详细信息的方向。

而这就是控制反转的思想。

应用依赖关系反转原则后,A 可以调用 B 实现的抽象上的方法,让 A 可以在运行时调用 B,而 B 又在编译时依赖于 A 控制的接口(因此,典型的编译时依赖项发生反转)。 运行时,程序执行的流程保持不变,但接口引入意味着可以轻松插入这些接口的不同实现。

上下不同的实现方式在于之前的依赖关系是A->B->C,控制反转后A->B接口->C接口,然后具体的B,C实现又是B->B接口的反转依赖。这样的好处就是A只依赖B接口而不是依赖实现,具体我们要实现是什么只需要按照业务需求进行编写,并且可以随时替换实现而不会影响A的实现,这种思想就是控制反转。

如下是顺序依赖:

        public class A
{
//依赖具体类
public B b;
public C c;
public A(B _b, C _c) {
b = _b;
c = _c;
}
public void Listen()
{
b.SayHi();
c.SayBye();
}
} public class B
{
public void SayHi()
{
Console.WriteLine("hi...");
}
}
public class C
{
public void SayBye()
{
Console.WriteLine("bye...");
}
}

如下是控制反转:

        public class A
{
//依赖接口
public IB b;
public IC c;
public A(IB _b, IC _c)
{
b = _b;
c = _c;
}
public void Listen()
{
b.SayHi();
c.SayBye();
}
} public interface IB
{
public void SayHi();
}
public interface IC
{
public void SayBye();
}

DI依赖注入

.NET 支持依赖关系注入 (DI) 软件设计模式,这是一种在类及其依赖项之间实现控制反转 (IoC) 的技术。

我们首先用代码来看什么是DI,在.net提供的扩展包Microsoft.Extensions.DependencyInjection中来完成DI,nuget安装。

然后我们实现接口B和接口C,实现我们可以说英语,也可以说汉语,我们在SayHi和SayBye中输出汉语。

        public class B : IB
{
public void SayHi()
{
Console.WriteLine("你好...");
}
} public class C : IC
{
public void SayBye()
{
Console.WriteLine("再见...");
}
}

然后在服务容器中注册依赖关系。 .NET 提供了一个内置的服务容器 IServiceProvider。 服务通常在应用启动时注册,并追加到 IServiceCollection。 添加所有服务后,可以使用 BuildServiceProvider 创建服务容器,然后在容器中直接取“要”对象而不用去管它如何实例化,并且DI具备传染性,假如B引用了D接口ID,那么我们注册B并在获取B实例时,引用的D也会实例化。

            //IServiceCollection 服务
IServiceCollection services = new ServiceCollection();
//服务注册
services.AddTransient<A>();
services.AddTransient<IB, B>();
services.AddTransient<IC, C>();
//创建服务容器
var serviceProvider = services.BuildServiceProvider();
//获取服务
var a = serviceProvider.GetRequiredService<A>();
//使用
a.Listen();
Console.ReadKey();

这就是通过DI依赖注入的方式来实现IOC的思想,或许你会好奇为什么我们不直接实例化A,然后在构造方法里面传进去就行了,也就不依赖DI实现了。但是如果程序结构更复杂些呢,比如我上面提到的B又有D,D又有F呢,这样我们在构造的时候不是一直要new很多对象,而且同一个接口的不同实现我们还要去找实例化处的代码进行修改。比如我SayHI我想说英文呢?那么我们假设实现一个BB,然后在服务注册的地方注册BB就可以了。

        public class BB : IB
{
public void SayHi()
{
Console.WriteLine("hello...");
}
}

然后注册BB services.AddTransient<IB, BB>(),而不用去改任何逻辑。

服务生命周期

在注册服务的时候我使用的AddTransient方法,表示注册的服务是瞬态的,也就是每次请求都是重新创建实例。同时还提供其它注册服务的方法。



服务有三种声明周期:

  • 瞬态
  • 作用域
  • 单例
  1. 瞬态

    服务是每次从服务容器进行请求时创建的。 这种生存期适合轻量级、 无状态的服务。 用 AddTransient 注册服务。在处理请求的应用中,在请求结束时会释放暂时服务。

  2. 作用域

    指定了作用域的生存期指明了每个客户端请求(连接)创建一次服务。 向 AddScoped 注册范围内服务。在处理请求的应用中,在请求结束时会释放有作用域的服务。

    想asp.net 在处理一个请求的时候是一个作用域,同样我们自己也可以定义作用域。使用serviceProvider.CreateScope()创建作用域,在作用域释放后对象将被释放。



    我们使用AddScoped添加对象,然后在作用域中取两个A对象进行比较,可以看到是True

    如果我们用AddTransient注册A,即使在作用域内两个对象比较也是不一样的,结果为False

  3. 单例

    单例大家应该好理解,就是设计模式中的单例,使用AddSingleton 注册,在首次请求它们时进行创建;或者在向容器直接提供实现实例时由开发人员进行创建。 很少用到此方法,因为可能是线程不安全的,如果服务中有状态。

其它

在Microsoft.Extensions.DependencyInjection中只能用构造函数注入,其它框架还提供属性注入,比如autofac。至于原因不得而知,当然也看个人喜好。查了些资料说是构造函数注入更科学,在对象创建的瞬间对象的构造方法将服务实例化,避免逻辑问题。

.net 温故知新:【7】IOC控制反转,DI依赖注入的更多相关文章

  1. laravel服务容器(IOC控制反转,DI依赖注入),服务提供者,门脸模式

    laravel的核心思想: 服务容器: 容器:就是装东西的,laravel就是一个个的对象 放入:叫绑定 拿出:解析 使用容器的目的:这里面讲到的是IOC控制反转,主要是靠第三方来处理具体依赖关系的解 ...

  2. Spring 04: IOC控制反转 + DI依赖注入

    Spring中的IOC 一种思想,两种实现方式 IOC (Inversion of Control):控制反转,是一种概念和思想,指由Spring容器完成对象创建和依赖注入 核心业务:(a)对象的创建 ...

  3. Spring专题2: DI,IOC 控制反转和依赖注入

    合集目录 Spring专题2: DI,IOC 控制反转和依赖注入 https://docs.spring.io/spring/docs/2.5.x/reference/aop.html https:/ ...

  4. Java Web实现IOC控制反转之依赖注入

    控制反转(Inversion of Control,英文缩写为IoC)是一个重要的面向对象编程的法则来削减计算机程序的耦合问题,也是轻量级的Spring框架的核心. 控制反转一般分为两种类型,依赖注入 ...

  5. (转)Ioc控制反转和依赖注入

    转载地址:https://zhuanlan.zhihu.com/p/95869440 控制反转控制反转(Inversion of Control,简称IoC),是面向对象编程中的一种设计思想,其作用是 ...

  6. Spring的IOC控制反转和依赖注入-重点-spring核心之一

    IoC:Inverse of Control(控制反转): 读作"反转控制",更好理解,不是什么技术,而是一种设计思想,好比于MVC.就是将原本在程序中手动创建对象的控制权,交由S ...

  7. spring IOC --- 控制反转(依赖注入)----简单的实例

    IoC(Inversion of Control)控制反转,对象创建责任的反转,在spring中BeanFacotory是IoC容器的核心接口,负责实例化,定位,配置应用程序中的对象及建立这些对象间的 ...

  8. 搞定.NET MVC IOC控制反转,依赖注入

    一直听说IOC,但是一直没接触过,只看例子好像很高达上的样子,今天抽了点时间实现了下,当然也是借助博客园里面很多前辈的文章来搞的!现在做个笔记,防止自己以后忘记! 1.首先创建MVC项目 2.然后新建 ...

  9. Java之控制反转和依赖注入

    1.简介 依赖注入和控制反转,目的是为了使类与类之间解耦合,提高系统的可扩展性和可维护性,下面通过一个例子来引入这一概念. 2.案例 1)一般情况下的类耦合 Main.java public clas ...

  10. java控制反转与依赖注入

    1.简介 依赖注入和控制反转,目的是为了使类与类之间解耦合,提高系统的可扩展性和可维护性,下面通过一个例子来引入这一概念. 2.案例 1)一般情况下的类耦合 Main.java public clas ...

随机推荐

  1. 一个恢复CSI挂载信息的解决方法

    一个恢复CSI挂载信息的解决方法 问题描述 之前有做过一个华为OBS 的CSI插件,其基本运作原理如下图所示.CSI插件Pod挂载了主机的/var/lib/kubelet/pods目录,当创建挂载Pv ...

  2. React history.push()无法跳转 url改变页面不渲染

    一.history.push()无法跳转参考了很多文章 研究一下生命周期 render是要有state变化才会执行 BrowserHistory只有props变化 无法触发render 如下改造环境 ...

  3. NPM Error:gyp: No Xcode or CLT version detected!

    问题 最近在macOS Catalina中使用npm安装模块,经常会出现如下错误: > node-gyp rebuild No receipt for 'com.apple.pkg.CLTool ...

  4. 一文带你了解J.U.C的FutureTask、Fork/Join框架和BlockingQueue

    摘要: J.U.C是Java并发编程中非常重要的工具包,今天,我们就来着重讲讲J.U.C里面的FutureTask.Fork/Join框架和BlockingQueue. 本文分享自华为云社区<[ ...

  5. 【2022-06-16】Pycharm的下载与安装使用

    一.Pycharm软件简介 产品简介 PyCharm是一种Python IDE(Integrated Development Environment,集成开发环境),带有一整套可以帮助用户在使用Pyt ...

  6. 26.MySQL数据库基础

    MySQL数据库基础 目录 MySQL数据库基础 数据库的概念 数据 表 数据库 数据库的管理系(DBMS) 数据库系统 访问数据库的流程 数据库系统发展史 当今主流数据库介绍 关系数据库 关系数据库 ...

  7. 互联网研发效能之去哪儿网(Qunar)核心领域DevOps落地实践

    本文从业务目标角度出发,确定了开源+自建模式搭建 Qunar 研发工具链整体生态:通过 APPCODE 打通工具链,流程规范化自动化:多种手段+发布门禁助力质量提升:建立应用画像确定运维最小单元,可发 ...

  8. MySQL通过binlog日志恢复数据

    一.查看下自己的MySQL是否开启了binlog日志 # 是否启用binlog日志 OFF:关闭 ON:开启 show variables like 'log_bin'; 二.开启binlog日志 在 ...

  9. C#实现一个万物皆可排序的队列

    需求 产品中需要向不同的客户推送数据,原来的实现是每条数据产生后就立即向客户推送数据,走的的是HTTP协议.因为每条数据都比较小,而数据生成的频次也比较高,这就会频繁的建立HTTP连接,而且每次HTT ...

  10. CANN算子:利用迭代器高效实现Tensor数据切割分块处理

    摘要:本文以Diagonal算子为例,介绍并详细讲解如何利用迭代器对n维Tensor进行基于位置坐标的大批量数据读取工作. 本文分享自华为云社区<CANN算子:利用迭代器高效实现Tensor数据 ...