ASP.NET Core - 依赖注入 自动批量注入

news2024/12/19 19:34:08

在这里插入图片描述

依赖注入配置变形

随着业务的增长,我们项目工作中的类型、服务越来越多,而每一个服务的依赖注入关系都需要在入口文件通过Service.Add{}方法去进行注册,这将是非常麻烦的,入口文件需要频繁改动,而且代码组织管理也会变得麻烦,非常不优雅。

在许多框架中会对这种通过 Service.Add{xxx} 的方式在代码中显式注册依赖注入关系的方式进行变形,有的可以通过配置文件进行注册,
这里稍微简单介绍一下依赖注入默认注册的原理,其实也就是通过放射的一些手段,再加上一些约定好的规则而已。

约定 实现类要接口结尾
》Izen 接口
》实现类 MyServiceZen

这里稍微简单介绍一下依赖注入默认注册的原理,其实也就是通过放射的一些手段,再加上一些约定好的规则而已。

public interface ISingleton
{
}
public interface IScoped
{
}
public interface ITransient
{
}

》》定义一个扩展类 实现 IServiceCollection 的扩展方法

namespace Microsoft.Extensions.DependencyInjection
{
    public static class ServiceCollectionDependencyExtensions
    {
        public static IServiceCollection AddAutoInject<T>(this IServiceCollection services)
        {
            var register = new ServiceRegister();
            register.AddAssembly(services, typeof(T).Assembly);
            return services;
        }
    }
}

》》》这个扩展方法中调用了注册器,往容器中注入服务,实现如下:


public class ServiceRegister
{
    public void AddAssembly(IServiceCollection services, Assembly assembly)
    {
        // 查找程序中的类型
        var types = assembly.GetTypes().Where(t => t != null && t.IsClass && !t.IsAbstract && !t.IsGenericType);
        // 遍历每一个类检查释放满足约定的规则
        foreach (var type in types)
        {
            AddType(services, type);
        }
    }

    /// <summary>
    /// 添加当前类型的依赖注入关系
    /// </summary>
    /// <param name="services"></param>
    /// <param name="type"></param>
    public void AddType(IServiceCollection services, Type type)
    {
        var lifetime = GetLifetimeOrNull(type);
        if (lifetime == null)
        {
            return;
      
        var exposeServices = ExposeService(type);
        foreach (var serviceType in exposeServices)
        {
            var serviceDescriptor = new ServiceDescriptor(serviceType, type, lifetime.Value);
            services.Add(serviceDescriptor);
        }
    }

    /// <summary>
    /// 根据标记接口确定生命周期,如果没有添加标记接口的,则不会被自动注册到容器
    /// </summary>
    /// <param name="type"></param>
    /// <returns></returns>
    public ServiceLifetime? GetLifetimeOrNull(Type type)
    {
        if (typeof(ISingleton).IsAssignableFrom(type))
        {
            return ServiceLifetime.Singleton;
      	}
        if(typeof(IScoped).IsAssignableFrom(type))
        {
            return ServiceLifetime.Scoped;
      	}
        if(typeof(ITransient).IsAssignableFrom(type))
        {
            return ServiceLifetime.Transient;
      	}
        return null;
    }
    /// <summary>
    /// 根据约定的规则查找当前类对于的服务类型
    /// 通过接口实现的方式,查找当前类实现的接口,如果一个接口名称去除了 "I" 之后与当前类的后半段一样,
    /// 则当前类应该被注册为这个接口的服务。
    /// </summary>
    /// <param name="type"></param>
    /// <returns></returns>
    public IList<Type> ExposeService(Type type)
    {
        var serviceTypes = new List<Type>();
        var interfaces = type.GetInterfaces();
        foreach (var interfacesType in interfaces)
        {
            var interfaceName = interfacesType.Name;
            if (interfaceName.StartsWith("I"))
            {
                interfaceName = interfaceName.Substring(1);
          	}
            if (type.Name.EndsWith(interfaceName))
            {
                serviceTypes.Add(interfacesType);
            }
        }
        return serviceTypes;
    }
}

整体的逻辑就是查找遍历程序集中的所有类型,并通过判别类型是否实现之前定好的三个生命周期接口,
从而确定类型是否需要自动注册到容器中,如果需要再根据约定好的规则获取需要注册的服务类型,并且构建服务描述器,再将其添加到容器中。

之后在入口文件中这样使用:
》builder.Services.AddAutoInject();

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

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

相关文章

Oracle 适配 OpenGauss 数据库差异语法汇总

背景 国产化进程中&#xff0c;需要将某项目的数据库从 Oracle 转为 OpenGauss &#xff0c;项目初期也是规划了适配不同数据库的&#xff0c;MyBatis 配置加载路径设计的是根据数据库类型加载指定文件夹的 xml 文件。 后面由于固定了数据库类型为 Oracle 后&#xff0c;只写…

Kubeadm+Containerd部署k8s(v1.28.2)集群(非高可用版)

Kubeadm+Containerd部署k8s(v1.28.2)集群(非高可用版) 文章目录 Kubeadm+Containerd部署k8s(v1.28.2)集群(非高可用版)一.环境准备1.服务器准备2.环境配置3.设置主机名4.修改国内镜像源地址5.配置时间同步6.配置内核转发及网桥过滤二.容器运行时Containerd安装(所有节点)…

[LeetCode-Python版]21. 合并两个有序链表(迭代+递归两种解法)

题目 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1&#xff1a; 输入&#xff1a;l1 [1,2,4], l2 [1,3,4] 输出&#xff1a;[1,1,2,3,4,4] 示例 2&#xff1a; 输入&#xff1a;l1 [], l2 [] 输出&#x…

MATLAB引用矩阵元素的几种方法

引用矩阵元素可以通过索引&#xff0c;也可以通过逻辑值 索引 通过引用元素在矩阵中的位置来提取元素&#xff0c;例如&#xff1a; - 逻辑值 通过某种逻辑运算来使得要提取的值变为逻辑 1 1 1&#xff0c;用 A ( ) A() A()提取即可&#xff0c; A A A为原矩阵的名称。 例如&…

sql 批量修改字段 的默认值

SELECT COLUMN_NAME, NUMERIC_PRECISION, NUMERIC_SCALE FROM information_schema.COLUMNS WHERE TABLE_SCHEMA financeproject AND TABLE_NAME finance_balance AND DATA_TYPE decimal; 查出的字段 excel 拼接 修改语句 ALTER TABLE finance_income MODIFY COLUMN yy…

CVE-2023-0562【春秋云镜】

目录 CVE-2023-0562漏洞概述漏洞利用方式影响范围修复建议安全编码示例靶标介绍 CVE-2023-0562 CVE-2023-0562 是一个针对银行储物柜管理系统的SQL注入漏洞。该漏洞影响了储物柜管理系统中处理用户输入的部分&#xff0c;攻击者可以利用此漏洞未经授权地访问数据库中的敏感信息…

vue el-dialog实现可拖拉

el-dialog实现拖拉&#xff0c;每次点击度居中显示&#xff0c;以下贴出代码具体实现&#xff0c;我是可以正常拖拉并且每次度显示在中间&#xff0c;效果还可以&#xff0c;需要的可以丢上去跑跑 组件部分&#xff1a; <el-dialog:visible.sync"dialogVisible"…

MySQL:库和表的操作

目录 一. 查看数据库 二. 创建数据库 三. 字符集和校验规则 四. 修改和删除数据库 4.1 数据库修改 4.2 数据库删除 五. 备份与恢复 5.1 备份 5.2 还原 5.3 注意事项 5.4 查看连接情况 六. 创建表 七. 查看表结构 八. 修改表 九. …

gitlab初始化+API批量操作

几年没接触gitlab了&#xff0c;新版本装完以后代码提交到默认的main分支&#xff0c;master不再是主分支 项目有几十个仓库&#xff0c;研发提交代码后仓库地址和之前的发生了变化 有几个点 需要注意 1、修改全局默认分支 2、关闭分支保护 上面修改了全局配置不会影响已经创…

Java集合(完整版)

集合框架 Collection集合 概念&#xff1a;对象的容器&#xff0c;定义了对多个对象进行操作的常用方法。可以实现数组的功能 和数组的区别&#xff1a; 数组的长度固定&#xff0c;集合长度不固定数组可以存储基本类型和引用类型&#xff0c;集合只能存储引用类型 Collec…

常耀斌:深度学习和大模型原理与实战(深度好文)

目录 机器学习 深度学习 Transformer大模型架构 人工神经元网络 卷积神经网络 深度学习是革命性的技术成果&#xff0c;有利推动了计算机视觉、自然语言处理、语音识别、强化学习和统计建模的快速发展。 深度学习在计算机视觉领域上&#xff0c;发展突飞猛进&#xff0c;…

不能通过 ip 直接访问 共享盘 解决方法

from base_config.config import OpenSMB, SMB import os, time, calendar, requests, decimal, platform, fs.smbfsinfo_dict SMB.EPDI_dict info_dict[host] (FS03,10.6.12.182) info_dict[direct_tcp] True# smb OpenSMB(info_dict)print(ok)# 根据 ip 查询电脑名 impor…

Mapbox-GL 的源码解读的一般步骤

Mapbox-GL 是一个非常优秀的二三维地理引擎&#xff0c;随着智能驾驶时代的到来&#xff0c;应用也会越来越广泛&#xff0c;关于mapbox-gl和其他地理引擎的详细对比&#xff08;比如CesiumJS&#xff09;&#xff0c;后续有时间会加更。地理首先理解 Mapbox-GL 的源码是一项复…

HIVE4.0.1在Hadoop HA部署hiveserver2模式

本文基于CENTOS7&#xff0c;在Hadoop3.4.0版本vm虚拟机3节点HA集群的基础上进行的搭建。 一、前置条件 本文使用MySQL8.0.26作为HIVE数据库&#xff0c;不使用hive自带的derby数据库&#xff0c;因为其不支持多客户端访问&#xff0c;也不方便查询。 所以必须先安装MySQL。版本…

Visual Studio 使用 GitHub Copilot 协助调试

&#x1f380;&#x1f380;&#x1f380;【AI辅助编程系列】&#x1f380;&#x1f380;&#x1f380; Visual Studio 使用 GitHub Copilot 与 IntelliCode 辅助编码Visual Studio 安装和管理 GitHub CopilotVisual Studio 使用 GitHub Copilot 扩展Visual Studio 使用 GitHu…

C10.【C++ Cont】字符数组和万能头

目录 1.字符数组 1.初始化 1.按字符串初始化 2.按字符初始化 2.字符串的输入 1.无空格的字符串 2.带空格的字符串 解决方法 1.gets(了解即可) gets不安全的原因 2.fgets 3.改良后的scanf 4.getchar 3.字符数组的输出 2.C万能头 1.字符数组 C语言风格的字符串:用…

[C++]C++工具之对异常情况的处理(throw、catch、try)以及用命名空间避免同名冲突

一、C 异常处理&#x1f60a; 1.1 定义 C 中的异常处理用于应对程序运行中的异常情况&#xff08;如除零、数组越界等&#xff09;&#xff0c;通过 try-catch 机制捕获和处理错误&#xff0c;防止程序崩溃。 异常是程序运行时意外发生的事件&#xff0c;可以通过抛出&#xf…

番外篇 | Hyper-YOLO:超图计算与YOLO架构相结合成为目标检测新的SOTA !

前言:Hello大家好,我是小哥谈。Hyper-YOLO,该方法融合了超图计算以捕捉视觉特征之间复杂的高阶关联。传统的YOLO模型虽然功能强大,但其颈部设计存在局限性,限制了跨层特征的融合以及高阶特征关系的利用。Hyper-YOLO在骨干和颈部的联合增强下,成为一个突破性的架构。在COC…

IDEA搭建springboot demo

如下所示创建SpringBootTest18项目&#xff0c;我选的maven&#xff0c;创建完成项目后&#xff0c;maven会自动下载一些依赖库到maven的repository目录中。 创建的项目结构如下图所示 接下来在项目中加入Framework支持&#xff0c;右击项目&#xff0c;弹出的菜单如下图所示&a…

vscode不同项目使用不同插件

转载请注明出处&#xff1a;小帆的帆的博客 在使用vscode开发不同项目时可能会用到不同的插件。手动管理不够优雅&#xff0c;本文介绍使用Profiles的方式的来管理不同项目的插件。 手动管理不同项目的插件 本来vscode安装了有三个插件 这时需要新建一个项目&#xff0c;新…