C# IOC 容器实战:KeyedService和生命周期

news2024/11/12 10:50:23

文章目录

  • 前言
  • KeyedService
    • Key缺少
    • Key值覆盖
  • KeyedService.AnyKey
  • 生命周期
    • 测试代码
  • 总结

前言

我之前写过一篇Ioc容器的使用,用的是微软的IOC容器。这次我们再去深入了解一下IOC 和控制反转

.NET Core 依赖注入 Microsoft.Extensions.DependencyInjection

ASP.NET CORE 内置的IOC解读及使用

ServiceCollection IOC容器 服务的生命周期

Dependency Injection 8.0新功能——KeyedService
作者: 寻己Tenleft
出处:https://www.cnblogs.com/tenleft/p/17719609.html
本站使用「CC BY 4.0」创作共享协议,转载请在文章明显位置注明作者及出处。

详解.NET依赖注入中对象的创建与“销毁”

KeyedService

使用Key值来对类进行区分。

Dependency Injection 8.0新功能——KeyedService

 public class Person
 {


     public List<Phone> Phones { get; set; }

     public Person() {
     
     }

     /// <summary>
     /// 使用拿到对应的
     /// </summary>
     /// <param name="phone1"></param>
     /// <param name="phone2"></param>
     public Person( [FromKeyedServices("A")] Phone phone1, [FromKeyedServices("B")] Phone phone2)
     {
         Phones = new List<Phone>
         {
             phone1,
             phone2
         };
     }
 }


 public class Phone
 {
     public string Name { get; set; }

     public Phone() { }
 }
static void Main(string[] args)
{

    IServiceCollection services = new ServiceCollection()
        .AddSingleton<Person>()
        .AddKeyedScoped<Phone>("A")
        .AddKeyedScoped<Phone>("B");

    var builder = services.BuildServiceProvider();
    
    builder.GetKeyedService<Phone>("A").Name = "大米";
    builder.GetKeyedService<Phone>("B").Name = "小花";

    var person = builder.GetService<Person>();

    Console.WriteLine(JsonConvert.SerializeObject(person));



    Console.WriteLine("运行完成!");
    Console.ReadKey();
}

在这里插入图片描述

也可以这么写

 static void Main(string[] args)
 {

     IServiceCollection services = new ServiceCollection()
         .AddSingleton<NetCore.Models.Person>()
         .AddKeyedScoped<Phone>("A", (sp,key) =>
         {
             return new Phone() {Name = "小花" };
         })
         .AddKeyedScoped<Phone>("B", (sp, key) =>
         {
             return new Phone() { Name = "大米" };
         });

     var builder = services.BuildServiceProvider();
     


     var person = builder.GetService<NetCore.Models.Person>();

     Console.WriteLine(JsonConvert.SerializeObject(person));



     Console.WriteLine("运行完成!");
     Console.ReadKey();
 }

Key缺少

如果Key的构造函数对应不上,就会出现问题

在这里插入图片描述
在这里插入图片描述

Key值覆盖

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

KeyedService.AnyKey

因为之前的KeyService的要求是必须声明,才能注入,如果缺一个就直接不走构造函数了,实在是太严格了。

使用KeyedService.AnyKey就是尽可能的获取对应的Key的服务

        static void Main(string[] args)
        {

            IServiceCollection services = new ServiceCollection()
                .AddSingleton<NetCore.Models.Person>()
                .AddKeyedScoped<Phone>(KeyedService.AnyKey);

            var builder = services.BuildServiceProvider();
            //builder.GetServices<Phone>();
            var res =  builder.GetKeyedService<Phone>("A");
            Console.WriteLine(res.Name);
            var person = builder.GetService<NetCore.Models.Person>();

            Console.WriteLine(JsonConvert.SerializeObject(person));



            Console.WriteLine("运行完成!");
            Console.ReadKey();
        }
public class Phone
{

    public string Name { get; set; }

    public Phone() { }

    /// <summary>
    /// 尝试去拿Key的值
    /// </summary>
    /// <param name="key"></param>
    public Phone([ServiceKey] string key )
    {
        Console.WriteLine($"我拿到Key了{key}");
    }
    
}

在这里插入图片描述

生命周期

详情可以看这篇文章,写的是真的厉害

详解.NET依赖注入中对象的创建与“销毁”

测试代码

  • this.GetHashCode()会返回每个新对象唯一的code,来区分对象
  • 继承IDisposable后,IOC容器会在合适的地方自动调用Dispose方法
public class SingleService : IDisposable
{
    public string Name { get; set; }

    public SingleService([ServiceKey] string key)
    {
        Name = key;
        Console.WriteLine($"我被创造了[{Name}]-{this.GetHashCode()}");
    }


    public void Dispose()
    {
        Console.WriteLine($"我被销毁了[{Name}]-{this.GetHashCode()}");

    }
}

public class ScopedService : IDisposable
{
    public string Name { get; set; }

    public ScopedService()
    {
        Console.WriteLine($"我被创造了[{Name}]-{this.GetHashCode()}");

    }

    public ScopedService([ServiceKey] string key)
    {
        Name = key;
        Console.WriteLine($"我被创造了[{Name}]-{this.GetHashCode()}");
    }


    public void Dispose()
    {
        Console.WriteLine($"我被销毁了[{Name}]-{this.GetHashCode()}");

    }


}

public class TransientService : IDisposable
{
    public string Name { get; set; }

    public TransientService([ServiceKey] string key)
    {
        Name = key;
        Console.WriteLine($"我被创造了[{Name}]-{this.GetHashCode()}");
    }



    public void Dispose()
    {
        Console.WriteLine($"我被销毁了[{Name}]-{this.GetHashCode()}");

    }
}

static void Main(string[] args)
{

    var services = new ServiceCollection()
        .AddKeyedSingleton<SingleService>(KeyedService.AnyKey)
        .AddKeyedScoped<ScopedService>(KeyedService.AnyKey)
        .AddKeyedTransient<TransientService>(KeyedService.AnyKey).BuildServiceProvider();

    Console.WriteLine();

    services.GetKeyedService<SingleService>("A");
    services.GetKeyedService<ScopedService>("B");
    services.GetKeyedService<TransientService>("C");
    Console.WriteLine();
    services.GetKeyedService<SingleService>("A");
    services.GetKeyedService<ScopedService>("B");
    services.GetKeyedService<TransientService>("C");

    //测试Scoped
    using (var scope = services.CreateScope())
    {
        Console.WriteLine("");

        scope.ServiceProvider.GetKeyedService<SingleService>("A");
        scope.ServiceProvider.GetKeyedService<ScopedService>("B");
        scope.ServiceProvider.GetKeyedService<TransientService>("C");
    }

    Console.WriteLine();

    Console.WriteLine("运行完成!");
    Console.ReadKey();
}

在这里插入图片描述

总结

这次算是补上了上次的坑,彻底弄懂了IOC 容器的生命周期。怎么玩我还不了解,懂了至少吹牛逼的时候有谈资。

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

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

相关文章

js 实现拖动按钮添加布局

效果&#xff1a; h布局生成左右布局&#xff0c; v布局生成上下布局 代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, ini…

【MATLAB源码-第104期】基于matlab的MPSK和MQAM调制解调方式仿真,输出误码率曲线。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 MPSK&#xff08;多相位键控&#xff09; MPSK是一种基于载波相位变化的数字调制技术。它的核心原理是通过改变载波的相位来表示不同的数字信息。这种技术可以分为几个不同的级别&#xff0c;其中最常见的包括&#xff1a; 1…

用sql计算两个日期的间隔天数 ,去除周末

快递行业&#xff0c;经常需要计算2个节点的时效&#xff0c;有的计算自然日&#xff0c;有时候需要计算去掉周末的时效&#xff0c;计算自然日很简单&#xff0c;用函数datediff 就可以了&#xff0c;计算工作日时效&#xff0c;我的实现方法如下&#xff0c;借助了一个日期维…

GSTAE

缺失数据的流量预测:一种多任务学习方法 摘要:基于真实交通数据的交通速度预测是智能交通系统(ITS)中的一个经典问题。大多数现有的交通速度预测模型都是基于交通数据完整或具有罕见缺失值的假设而提出的。然而,由于各种人为和自然因素,在现实场景中收集的此类数据往往是…

NUS CS1101S:SICP JavaScript 描述:二、使用数据构建抽象

原文&#xff1a;2 Building Abstractions with Data 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 我们现在来到数学抽象的决定性步骤&#xff1a;我们忘记符号代表什么。…[数学家]不需要闲着&#xff1b;他可以用这些符号进行许多操作&#xff0c;而无需看它们所代…

Elasticsearch 7.8.0从入门到精通

安装Elasticsearch 7.8.0 官网&#xff1a;Elasticsearch 7.8.0 | Elastic 大家下载所需要的安装包即可。然后解压缩&#xff1a; Elasticsearch是通过java编写的&#xff0c;所以自带jdk。多好&#xff0c;下载Elasticsearch赠送jdk 0.0&#xff0c;不过一般我们用自己的jdk…

C++学习笔记——输入、输出和文件

目录 一、标准输入输出 2.1下面是它们的基本用法 解释 二、格式化输入输出 2.2下面是一个示例 解释 三、文件读写 3.3下面是一个文件读写的示例 解释 四、异常处理和错误检测 4.1下面是一个示例 解释 五、一个实例代码 5.1如何读取 CSV 文件&#xff0c;并计算每…

QToolBar、QStatusBar和QDockWidget的使用

1. 工具栏 QToolBar 1.1 创建工具栏 1.1.1 工具栏的基本函数 设置工具栏的停靠区域 参数 Qt::LeftToolBarArea //左边 Qt::RightToolBarArea //右边 Qt::TopToolBarArea //顶部 Qt::BottomToolBarArea //底部 Qt::AllToolBarAreas //所有区域 Qt::NoToolBarArea //没有QMa…

基于NLP的恶意网页识别

基于NLP的恶意网页识别 基于NLP的恶意网页识别引言项目目录回顾优化HTML标签提取结果使用预训练模型Fine-tune数据处理和模型训练模型训练与评估模型导出部署与预测总结 基于NLP的恶意网页识别 引言 欢迎阅读《 基于NLP的恶意网页识别》&#xff0c;在前三篇中&#xff0c;我…

如何保证数据库和缓存双写一致性-----一篇足以

保证数据库和缓存双写一致性的必要性和优点在于确保系统数据的准确性和可靠性。通过双写一致性机制&#xff0c;系统可以防止因为缓存数据与数据库数据不一致而导致的业务错误。这种做法有效降低了系统的脆弱性&#xff0c;提高了数据的完整性。同时&#xff0c;通过缓存加速读…

AI智能分析网关V4烟火检测算法解决方案

一、背景需求 根据国家消防救援局公布的数据显示&#xff0c;2023年共接报处置各类警情213.8万起&#xff0c;督促整改风险隐患397万处。火灾危害巨大&#xff0c;必须引起重视。传统靠人工报警的方法存在人员管理难、场地数量多且分散等问题&#xff0c;无法有效发现险情降低…

部署Tomcat及其负载均衡

简介 在前面已经学习了Nginx服务器的安装配置&#xff0c;本章主要采用案例课的形式介绍Tomcat及NginxTomcat负载均衡群集。Tomcat案例首先介绍其应用场景&#xff0c;然后重点介绍Tomcat的安装配置&#xff0c;NginxTomcat负载均衡群集案例是应用于生产环境下的一套可靠的Web站…

牛仔行头目标检测竞赛 李沐老师Kaggle(有代码有注释)

一、比赛地址 CowBoy Outfits Detection | Kaggle 二、数据介绍 这次比赛的数据集一共有4879个image&#xff0c;需要自己划分训练集和验证集。annotation的格式是json&#xff0c;因此如果用yolo系列的算法会涉及到json2txt这一步。当然如果不用yolo系列的就不要这段代码了。…

[vivado ] report_utilization -name

可以Open Synthesiezed或 Implementation 后的Design使用下面的命令&#xff0c;一定要加-name这个option, 后面的utilization_1可以可以自定义。 report_utilization -name utilization_1

【Python机器学习】分类器的不确定估计——预测概率

predict_proba的输出是每个类别的概率&#xff0c;通常比decision_function的输出更容易理解&#xff0c;对于二分类问题&#xff0c;它的形状始终是(n_samples,2)。 import mglearn.tools from sklearn.ensemble import GradientBoostingClassifier from sklearn.datasets im…

从DETR到Mask2Former(3):masked attention的attention map可视化

Mask2Former的论文中有这样一张图&#xff0c;表示masked attenion比cross attention效果要好 那么这个attention map是怎么画出来的&#xff1f; 在mask2attention的源代码中 CrossAttentionLayer这个类中&#xff0c;在forward_post函数中做如下修改&#xff1a; def forwar…

轴组【CAN】

如果有126个轴&#xff0c;你程序里挨个添加轴很麻烦。 可以用轴组批量添加。【数组】 CAN驱动器 0x164 就是下个驱动器 p_CAN主站地址:ADR(IoConfig_Globals.CANopen_Manager_SoftMotion);p_CAN从站地址1:ADR(IoConfig_Globals.DMA882_CAN);p_CAN从站地址2:ADR(IoConfig_Gl…

重磅!OpenAI正式发布,自定义ChatGPT商店!

1月11日凌晨&#xff0c;OpenAI在官网正式发布了&#xff0c;自定义GPT商店&#xff0c;可以帮助用户找到目前最好用、流行的自定义ChatGPT助手。 在2024年第一季度&#xff0c;OpenAI将启动GPT 开发者收入计划。首先&#xff0c;美国地区的开发者将根据用户对其 GPT 的使用情…

HTML--超链接

超链接 作用&#xff1a;点击跳转到相应位置 a标签 语法&#xff1a; <a href"链接地址">文本或图片</a>范例&#xff1a; <!DOCTYPE html> <html> <head> <meta charset"utf-8"/><title>跳转到百度</t…

蓝桥杯单片机进阶教程4——需要分配进程的模块

前言&#xff1a; 【蓝桥杯单片机保姆级教学】 https://www.bilibili.com/video/BV1h3411m7Aw/?p117&share_sourcecopy_web&vd_sourcec4fc67867c5218768e783d04475bc5a2 P117-118 比赛的时候也按照这个顺序来写 一、数码管显示 分析考题 &#xff08;1&#xff09;…