.net程序开发IOC控制反转和DI依赖注入详解

目录
  • IOC控制反转
  • DI依赖注入
  • 服务生命周期
  • 其它

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方法,表示注册的服务是瞬态的,也就是每次请求都是重新创建实例。同时还提供其它注册服务的方法。

服务有三种声明周期:

瞬态

作用域

单例

  • 瞬态

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

  • 作用域

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

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

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

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

  • 单例

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

其它

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

以上就是.net程序开发IOC控制反转和DI依赖注入详解的详细内容,更多关于.net 控制反转依赖注入的资料请关注我们其它相关文章!

(0)

相关推荐

  • ASP.NET Core依赖注入系列教程之控制反转(IoC)

    前言 ASP.NET Core在启动以及后续针对每个请求的处理过程中的各个环节都需要相应的组件提供相应的服务,为了方便对这些组件进行定制,ASP.NET通过定义接口的方式对它们进行了"标准化",我们将这些标准化的组件称为服务,ASP.NET在内部专门维护了一个DI容器来提供所需的服务.要了解这个DI容器以及现实其中的服务提供机制,我们先得知道什么是DI(Dependence Injection),而一旦我们提到DI,又不得不说IoC(Inverse of Control). 一.流程控

  • .Net Core依赖注入IOC和DI介绍

    名词解释 说起依赖注入,很多人会想起两个词:IOC和DI. IOC(Inversion of Control)=控制反转 DI(Dependency Injection)=依赖注入 IOC其实并不是某项具体的实现技术,它是一种思路(或者是设计理念),这一点很多有经验的同学都会搞混.如果用白话来讲,IOC就意味着把对象交给IOC容器控制,而不是在对象内部控制.简而言之就是“容器控制对象”. 套入到程序来说,我们有两个class,A.B,如果B要用到A的方法,传统的方法是在B中添加A的引用(比如ne

  • .NET IoC模式依赖反转(DIP)、控制反转(Ioc)、依赖注入(DI)

    依赖倒置原则(DIP) 依赖倒置(Dependency Inversion Principle,缩写DIP)是面向对象六大基本原则之一.他是指一种特定的的解耦形式,使得高层次的模块不依赖低层次的模块的实现细节,依赖关系被颠倒(反转),从而使得低层次模块依赖于高层次模块的需求抽象. 该原则规定: 高层次的模块不应该依赖低层次模块,二者都应该依赖其抽象接口. 抽象接口不应该依赖于具体实现,而具体实现则应该依赖于抽象接口. 通过如下一个简单的示例,我们来看一下,我们通过一个简单地下单流程向我们的用户发

  • ASP.NET Core应用中与第三方IoC/DI框架的整合

    一.ConfigureServices方法返回的ServiceProvider没有用! 我们可以通过一个简单的实例来说明这个问题.我们先定义了如下这个一个MyServiceProvider,它实际上是对另一个ServiceProvider的封装.简单起见,我们利用一个字典来保存服务接口与实现类型的映射关系,这个关系可以通过调用Registe方法来注册.在提供服务实例的GetService方法中,如果提供的服务类型已经被注册,我们会创建并返回对应的实例对象,否则我们将利用封装的这个ServiceP

  • .NET Core使用Autofac容器的DI依赖注入,IOC控制反转及AOP切面编程

    目录 Autofac 容器 Autofac 多种注入方式 Autofac 生命周期 Autofac 支持配置文件 Autofac 整合 .NET 5 MVC Autofac 支持控制器属性注入 Autofac 单实例多实现 Autofac 支持 AOP Autofac 容器 Autofac 是一款.NET IoC 容器 . 它管理类之间的依赖关系, 从而使 应用在规模及复杂性增长的情况下依然可以轻易地修改 . 它的实现方式是将常规的.net类当做组件处理. 安装 NuGet 程序包: Autof

  • .net程序开发IOC控制反转和DI依赖注入详解

    目录 IOC控制反转 DI依赖注入 服务生命周期 其它 IOC控制反转 大部分应用程序都是这样编写的:编译时依赖关系顺着运行时执行的方向流动,从而生成一个直接依赖项关系图. 也就是说,如果类 A 调用类 B 的方法,类 B 调用 C 类的方法,则在编译时,类 A 将取决于类 B,而 B 类又取决于类 C 应用程序中的依赖关系方向应该是抽象的方向,而不是实现详细信息的方向.而这就是控制反转的思想. 应用依赖关系反转原则后,A 可以调用 B 实现的抽象上的方法,让 A 可以在运行时调用 B,而 B

  • php中Ioc(控制反转)和Di(依赖注入)

    先看一个例子: <?php class A { public $b; public $c; public function A() { //TODO } public function Method() { $this->b=new B(); $this->c=new C(); $this->b->Method(); $this->c->Method(); //TODO } } class B { public function B() { //TODO } pu

  • Spring的DI依赖注入详解

    目录 1.什么是DI依赖注入? 2.利用 set 方法给属性赋值 3.利用 构造函数 给属性赋值 总结: 1.什么是DI依赖注入? spring动态的向某个对象提供它所需要的其他对象.这一点是通过DI(Dependency Injection,依赖注入)来实现的.比如对象A需要操作数据库,以前我们总是要在A中自己编写代码来获得一个Connection对象,有了 spring我们就只需要告诉spring,A中需要一个Connection,至于这个Connection怎么构造,何时构造,A不需要知道

  • Java使用IOC控制反转的三种设计模式详解

    对于许多开发人员来说,控制反演(IoC)都是一个模糊的概念,因为他们在现实世界中很少或没有被应用过.在最好的情况下,控制反演(IoC)可以加单的认为是等效于依赖注入(DI).实际上,只有在翻转控制与依赖注入双方都只是反映翻转依赖管理控制的时候,才认为两者是等效的.虽然,依赖注入实际上是IoC的一种众所周知的形式.但是,事实上IoC却是一个相对更为广泛的软件设计范例,可以通过多种模式来进行实现.在本文中,我们将介绍依赖注入,观察者模式和模板方法模式如何实现控制反转的. 正如许多其他设计模式,是从各

  • Spring bean的实例化和IOC依赖注入详解

    前言 我们知道,IOC是Spring的核心.它来负责控制对象的生命周期和对象间的关系. 举个例子,我们如何来找对象的呢?常见的情况是,在路上要到处去看哪个MM既漂亮身材又好,符合我们的口味.就打听她们的电话号码,制造关联想办法认识她们,然后...这里省略N步,最后谈恋爱结婚. IOC在这里就像婚介所,里面有很多适婚男女的资料,如果你有需求,直接告诉它你需要个什么样的女朋友就好了.它会给我们提供一个MM,直接谈恋爱结婚,完美! 下面就来看Spring是如何生成并管理这些对象的呢? 1.方法入口 o

  • 在.NET Core控制台程序中如何使用依赖注入详解

    背景介绍 Dependency Injection:又称依赖注入,简称DI.在以前的开发方式中,层与层之间.类与类之间都是通过new一个对方的实例进行相互调用,这样在开发过程中有一个好处,可以清晰的知道在使用哪个具体的实现.随着软件体积越来越庞大,逻辑越来越复杂,当需要更换实现方式,或者依赖第三方系统的某些接口时,这种相互之间持有具体实现的方式不再合适.为了应对这种情况,就要采用契约式编程:相互之间依赖于规定好的契约(接口),不依赖于具体的实现.这样带来的好处是相互之间的依赖变得非常简单,又称松

  • spring中IOC控制反转依赖注入和new对象的区别说明

    目录 IOC控制反转依赖注入和new对象的区别 new对象 依赖注入 spring的IOC容器比New对象究竟好在哪 IOC控制反转依赖注入和new对象的区别 spring默认是单例模式的,依赖注入其中操作的都是一个对象 new对象 单例中如果要做到注入的效果就是在类的头部进行实例化对象,这个时候该对象不管使用与否都贯穿该类的始终.该类对象不被回收,这个实例化对象也不会被回收,因为存在引用状态.如果要使用多例对象则最好使用new创建对象而不是依赖注入,即使依赖注入有多例模式也不推荐. 依赖注入:

  • Spring框架中IoC容器与DI依赖注入教程

    目录 一.Spring 是什么 1.1 什么是容器 1.2 什么是 IoC 二.理解 IoC 2.1 传统程序开发的问题 2.2 分析 2.3 控制反转式程序开发 2.4 对比总结规律 2.5 理解 Spring IoC 三.DI 概念说明 四.总结 一.Spring 是什么 我们通常所说的 Spring 指的是 Spring Framework (Spring 框架),它是⼀个开源框架,有着活跃而庞大的社区,这就是它之所以能长久不衰的原因.Spring ⽀持⼴泛的应⽤场景,它可以让 Java

  • 浅谈spring DI 依赖注入方式和区别

    目录 spring DI 3种DI注解的区别 1 @Autowired 2 @Inject 3 @Resource 3种注入方式的区别 1 field注入 2 构造器注入 3 setter注入 构造器注入的好处 1 依赖不可变 2 依赖不为空 3 完全初始化状态 4 避免循环依赖 5 总结 spring DI Spring框架对Java开发的重要性不言而喻,其核心特性就是IOC(Inversion of Control, 控制反转)和AOP,平时使用最多的就是其中的IOC,我们通过将组件交由Sp

随机推荐