我的编程空间,编程开发者的网络收藏夹
学习永远不晚

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

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

.net程序开发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 控制反转依赖注入的资料请关注编程网其它相关文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

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

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

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

这篇文章主要为大家介绍了.net程序开发IOC控制反转和DI依赖注入示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2022-11-13

理解Spring中的依赖注入和控制反转

学习过Spring框架的人一定都会听过Spring的IoC(控制反转) 、DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC 、DI这两个概念是模糊不清的,是很难理解的,今天和大家分享网上的一些技术大牛们对Spring框
2023-05-30

Laravel 服务容器实例教程 —— 深入理解控制反转和依赖注入

容器,字面上理解就是装东西的东西。常见的变量、对象属性等都可以算是容器。一个容器能够装什么,全部取决于你对该容器的定义。
2022-06-01

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录