C# “依赖注入” 中的 “三种生命周期”

news2024/12/24 9:09:03

🚀简介

依赖注入(Dependency Injection,简称DI)是一种实现控制反转(IoC)的技术,用于减少代码之间的耦合度。通过依赖注入,一个类可以从外部获取其依赖的对象,而不是自己创建。这样可以使得代码更加模块化,更易于测试和维护。

🐳依赖注入的生命周期主要有以下三种:

  1. Transient:每次请求都会创建一个新的实例。这是最常见的生命周期选项。
  2. Scoped:在同一次请求中始终返回同一实例。如果在不同的请求中,将会创建一个新的实例。
  3. Singleton:每次请求都返回同一个实例,即在首次请求时创建的实例。

🚀安装NuGet包

首先,我们先安装 Microsoft.Extensions.DependencyInjection:这是Microsoft提供的依赖注入框架。

🚀Transient

创建一个类,包含一个属性(Name)和一个方法(SayHi)

public class TestServicesImp
{
    public string Name { get; set; }
    
    public void SayHi()
    {
        Console.WriteLine("Hello:"+Name);
    }
}

👻通过ServiceCollection创建了一个服务容器,然后通过AddTransient方法将TestServicesImp类型注册到这个服务容器中。这里使用的是瞬时生命周期,也就是每次从容器中获取TestServicesImp类型时,都会创建一个新的实例。

public class Program
{
    public static void Main(string[] args)
    {
        var serviceCollection = new ServiceCollection();
        serviceCollection.AddTransient<TestServicesImp>();
        using (ServiceProvider sp = serviceCollection.BuildServiceProvider())
        {
            var t1 = sp.GetService<TestServicesImp>();
            t1.Name = "张三";
            t1.SayHi();

            var t2 = sp.GetService<TestServicesImp>();
            t2.Name = "李四";
            t2.SayHi();

            var referenceEquals = object.ReferenceEquals(t1, t2);
            Console.WriteLine(referenceEquals);
        }
    }
}

运行结果!因为在瞬时生命周期中,每次获取服务都会创建新的实例。 因此通过object.ReferenceEquals方法比较了t1和t2是否是同一个实例,结果会输出false

🚀 Scoped

我们将上面代码中的服务注册AddTransient方法换成AddScoped,然后t2.SayHi();换成t1.SayHi();,再试一次。

    public static void Main(string[] args)
    {
        var serviceCollection = new ServiceCollection();
        serviceCollection.AddScoped<TestServicesImp>();
        using (ServiceProvider sp = serviceCollection.BuildServiceProvider())
        {
            var t1 = sp.GetService<TestServicesImp>();
            t1.Name = "张三";
            t1.SayHi();

            var t2 = sp.GetService<TestServicesImp>();
            t2.Name = "李四";
            t1.SayHi();

            var referenceEquals = object.ReferenceEquals(t1, t2);
            Console.WriteLine(referenceEquals);
        }
    }

发现这次的比较结果为true,并且第二次调用SayHi也是使用t1,但依然输出了李四,因此可以得出,两次获取服务得到的是同一个实例。

 👻我们对代码再进行改造一下,创建一个新的服务作用域,通过这个作用域的ServiceProvider对象获取了另一个TestServicesImp的实例t2。

    public static void Main(string[] args)
    {
        var serviceCollection = new ServiceCollection();
        serviceCollection.AddScoped<TestServicesImp>();
        using (ServiceProvider sp = serviceCollection.BuildServiceProvider())
        {
            var t1 = sp.GetService<TestServicesImp>();
            t1.Name = "张三";


            using (IServiceScope scope = sp.CreateScope())
            {
                var t2 = scope.ServiceProvider.GetService<TestServicesImp>();
                t2.Name = "李四";

                t1.SayHi();
                t2.SayHi();
                
                var referenceEquals = object.ReferenceEquals(t1, t2);
                Console.WriteLine(referenceEquals);
            }
        }
    }

因为它们是在不同的Scope中获取的,所以这次的结果是false

 

🚀Singleton 

我们将服务注册AddScoped方法,换成AddSingleton,然后再执行一次

    public static void Main(string[] args)
    {
        var serviceCollection = new ServiceCollection();
        serviceCollection.AddSingleton<TestServicesImp>();
        using (ServiceProvider sp = serviceCollection.BuildServiceProvider())
        {
            var t1 = sp.GetService<TestServicesImp>();
            t1.Name = "张三";


            using (IServiceScope scope = sp.CreateScope())
            {
                var t2 = scope.ServiceProvider.GetService<TestServicesImp>();
                t2.Name = "李四";

                t1.SayHi();
                t2.SayHi();
                
                var referenceEquals = object.ReferenceEquals(t1, t2);
                Console.WriteLine(referenceEquals);
            }
        }
    }

在输出结果中很显然可以看出使用AddSingleton注册服务,每次请求都返回同一个实例

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1148911.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MyBatis-Plus 与 Druid 结合 Dynamic-datasource 实现多数据源操作数据库

MyBatis-Plus 官网&#xff1a;https://baomidou.com/ MyBatis-Plus 官方文档&#xff1a;https://baomidou.com/pages/24112f/ dynamic-datasource 文档&#xff08;付费&#xff09;&#xff1a;https://www.kancloud.cn/tracy5546/dynamic-datasource/2264611 创建数据库…

EM算法解析+代码

大纲 数学基础&#xff1a;凸凹函数&#xff0c;Jensen不等式&#xff0c;MLEEM算法公式&#xff0c;收敛性HMM高斯混合模型 一、数学基础 1. 凸函数 通常在实际中&#xff0c;最小化的函数有几个极值&#xff0c;所以最优化算法得出的极值不确实是否为全局的极值&#xff…

腾讯云2023年双11服务器优惠活动及价格表

腾讯云2023年双11大促活动正在火热进行中&#xff0c;腾讯云推出了一系列服务器优惠活动&#xff0c;云服务器首年1.8折起&#xff0c;买1年送3个月&#xff01;境外云服务器15元/月起&#xff0c;买更多省更多&#xff01;下面给大家分享腾讯云双11服务器优惠活动及价格表&…

Ps:平滑选区边缘

Ps 中某些传统的选区工具&#xff0c;如快速选择工具等&#xff0c;在进行选区后容易产生锯齿状等不规则的边界。此时&#xff0c;可利用“选择并遮住”来平滑选区边缘。 ◆ ◆ ◆ 操作方法与技巧 1、&#xff08;可选&#xff09;新建纯色填充图层&#xff0c;并置于原图图层…

【论文精读1】MVSNet架构各组织详解

一、训练流程 1. 特征提取 提取N个输入图像的深层特征用作深度匹配 与传统三维重建方法类似&#xff0c;第一步是提取图像特征&#xff08;SIFT等特征子&#xff09;&#xff0c;不同点在于本文使用8层的卷积网络从图像当中提取更深层的图像特征表示&#xff0c;网络结构如下…

ProEssentials pro v9 历史更新列表--注册版

ProEssentials标准版和专业版之间的唯一区别是可以渲染的数据点和注释的数量。标准版与专业版一样拥有所有的功能和接口。所有版本包括WPF、WinForm、WebForm、ActiveX、VCL和DLL接口。标准版仅限于8000个数据点和800个图表注释。此限制适用于每个控件实例。你可以运行多个控件…

《数字图像处理-OpenCV/Python》连载(33)使用掩模图像控制处理区域

**本书京东优惠购书链接&#xff1a;https://item.jd.com/14098452.html** **本书CSDN独家连载专栏&#xff1a;https://blog.csdn.net/youcans/category_12418787.html** 第 5 章 图像的算术运算 在OpenCV中&#xff0c;图像是以Numpy数组格式存储的&#xff0c;图像的算术运…

抓包分析DSCP字段在FTP/RSTP协议中的应用

抓包分析DSCP字段在FTP协议中的应用 简介 本文介绍DSCP字段的作用&#xff0c;以及抓包分析DSCP字段在FTP协议中的应用。最后通过实验证明有可能DSCP字段实际上对普通用户没啥用&#xff0c;原因是运营商可能会将用户设置的DSCP字段重置。 DSCP IP报文中有个TOS字段 &#…

C语言选择排序

1.选择排序(Selection sort) 选择排序是简单直观的排序算法。 基本思想&#xff1a;从首元素开始&#xff0c;首元素与它后面的所有元素进行比较&#xff0c;找到数列中最小的元素&#xff0c;与首元素值交换。然后下一个元素与它后面的元素比较&#xff0c;得到第二小的元素…

Zynq UltraScale+ XCZU5EV 纯VHDL解码 IMX214 MIPI 视频,2路视频拼接输出,提供vivado工程源码和技术支持

目录 1、前言免责声明 2、我这里已有的 MIPI 编解码方案3、本 MIPI CSI2 模块性能及其优越性4、详细设计方案设计原理框图IMX214 摄像头及其配置D-PHY 模块CSI-2-RX 模块Bayer转RGB模块伽马矫正模块VDMA图像缓存Video Scaler 图像缓存DP 输出 5、vivado工程详解PL端FPGA硬件设计…

C语言实现输入 n 个字符串,把其中以字母 A 打头的字符串输出

完整代码&#xff1a; // 输入 n 个字符串&#xff0c;把其中以字母 A 打头的字符串输出。 #include<stdio.h> #include<stdlib.h> //字符串的最大长度 #define N 20int main(){int n;printf("请输入字符串个数n:");scanf("%d",&n);//读取…

使用OBS Browser+访问华为云OBS存储【Windows】

背景 项目中使用华为云 S3 存储,java 代码中通过华为云 OBS 提供的esdk-obs-java 来访问文件。 但是,通过 JAVA SDK 方式不太方便运维,所以我们需要一款可视化的客户端软件。 华为云 OBS 自身也提供了一款客户端软件,名为 OBS Browser+。 OBS Browser+简介 OBS Browse…

【洛谷算法题】P5709-Apples Prologue / 苹果和虫子【入门2分支结构】

&#x1f468;‍&#x1f4bb;博客主页&#xff1a;花无缺 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 花无缺 原创 收录于专栏 【洛谷算法题】 文章目录 【洛谷算法题】P5709-Apples Prologue / 苹果和虫子【入门2分支结构】&#x1f30f;题目描述&am…

深入理解指针3

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 1. 字符指针变量 2. 数组指针变量 2.1 数组指针变量是什么&#xff1f; 2.2 数组指针变量怎么初始化 3. 二维数组传参的本质 4. 函数指针变量 4.1 函数指针变量的创…

比亚迪应届生爆料,真实的工作状态!

一位比亚迪的应届生发帖子称&#xff0c;校招入职比亚迪一个月&#xff0c;爱上了这里的工作文化&#xff0c;不怎么加班&#xff0c;工作日常就是开会对问题&#xff0c;顺便吵架扯皮&#xff0c;不用写令人头疼的代码&#xff0c;但是却拿着高工资&#xff0c;感觉现在的生活…

详解类生到死的来龙去脉

类生命周期和加载过程 一个类在 JVM 里的生命周期有 7 个阶段&#xff0c;分别是加载&#xff08;Loading&#xff09;、校验&#xff08;Verification&#xff09;、准备&#xff08;Preparation&#xff09;、解析&#xff08;Resolution&#xff09;、初始化&#xff08;Ini…

C++ 内存

内存分区模型 代码区&#xff1a;存放函数体的二进制代码&#xff0c;由操作系统进行管理全局区&#xff1a;存放全局变量和静态变量以及常量栈区&#xff1a;由编译器自动分配释放&#xff0c;存放函数的参数值、局部变量等堆区&#xff1a;由程序员分配和释放&#xff0c;若…

C#,数值计算——分类与推理Svmlinkernel的计算方法与源程序

1 文本格式 using System; namespace Legalsoft.Truffer { public class Svmlinkernel : Svmgenkernel { public int n { get; set; } public double[] mu { get; set; } public Svmlinkernel(double[,] ddata, double[] yy) : base(yy, ddata) …

SSM游戏购物商城

摘 要 信息化爆炸的时代&#xff0c;互联网技术的指数型的增长&#xff0c;信息化程度的不断普及&#xff0c;社会节奏在加快&#xff0c;每天都有大量的信息扑面而来&#xff0c;人们正处于数字信息化世界。数字化的互联网具有便捷性&#xff0c;传递快&#xff0c;效率高&am…

二叉树问题——前/中/后/层遍历(递归与栈)

摘要 博文主要介绍二叉树的前/中/后/层遍历(递归与栈)方法 一、前/中/后/层遍历问题 144. 二叉树的前序遍历 145. 二叉树的后序遍历 94. 二叉树的中序遍历 102. 二叉树的层序遍历 二、二叉树遍历递归解析 // 前序遍历递归LC144_二叉树的前序遍历 class Solution {publi…