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. Java内存分析——JavaSE基础

    内存分析 堆:存放new的对象和数组,可以被所有线程共享,不会存放别的对象引用 栈 存放基本变量类型(会包含这个基本类型的具体数值) 引用对象的变量(会存放这个引用在堆里的具体地址) 方法区(属于堆的 ...

  2. 定制.NET 6.0的依赖注入

    大家好,我是张飞洪,感谢您的阅读,我会不定期和你分享学习心得,希望我的文章能成为你成长路上的垫脚石,让我们一起精进. 在本章中,我们将学习ASP.NET Core的依赖项注入(DI)以及如何自定义它. ...

  3. 爱快在PVE下不定时反复重启死机的解决方法

    太长不看版本: 爱快3.6.X在PVE乃至于ESXI下都存在一定的兼容问题! 官网下载3.6.X安装后进入系统设置-升级备份-版本升级,使用爱快3.4.9bin升降级包,下载其中的bin升降级包,将爱 ...

  4. html实现3d视觉特效

    <html> <head> <title>HTML5实现3D球效果</title> <style type="text/css" ...

  5. 解决Invalid bound statement (not found)的异常

    今天在搭建框架的时候,报了一个Invalid bound statement (not found)的异常 经过分析,得出原因: 我的mybatis相关的dao和mapper.xml是通过逆向工程生成 ...

  6. 16.Nginx优化与防盗链

    Nginx优化与防盗链 目录 Nginx优化与防盗链 隐藏版本号 修改用户与组 缓存时间 日志切割 小知识 连接超时 更改进程数 配置网页压缩 配置防盗链 配置防盗链 隐藏版本号 可以使用 Fiddl ...

  7. 【Azure 应用服务】App Service 开启了私有终结点(Private Endpoint)模式后,如何来实现公网Git部署呢?

    问题描述 因为中国区的App Service对外(公网访问)需要进行ICP备案,所以很多情况下,Web应用部署到App Service后,都是通过Application Gateway(应用程序网关) ...

  8. SAP 实例 6 HTML input

    REPORT demo_html_input. CLASS demo DEFINITION. PUBLIC SECTION. CLASS-METHODS main. PRIVATE SECTION. ...

  9. 梯度下降算法实现原理(Gradient Descent)

    概述   梯度下降法(Gradient Descent)是一个算法,但不是像多元线性回归那样是一个具体做回归任务的算法,而是一个非常通用的优化算法来帮助一些机器学习算法求解出最优解的,所谓的通用就是很 ...

  10. 【Java面试】RDB 和 AOF 的实现原理、优缺点

    Hi,大家好,我是Mic. 一个工作了5年的粉丝私信我,最近面试碰到很多Redis相关的问题. 其中一个面试官问他Redis里面的持久化机制,没有回答得很好. 希望我帮他系统回答一下. 关于Redis ...