C# 当前项目自动服务DI类

这篇具有很好参考价值的文章主要介绍了C# 当前项目自动服务DI类。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

思路

我发现 .NET Core WebAPi项目有一个与Springboot的不同之处,就是Springboot项目有自动装配机制,他可以将在src下面与启动类在同一级包目录下的类进行扫描注册

而之前我了解到Springboot的自动装配机制本质上也就是通过扫描对应包,然后进行通过它自身进行服务注册,我虽然写不出那么牛掰的东西,但是我也打算大致仿照一下

步骤如下:

  1. 准备几个装饰类Server、Config等
  2. 扫描当前程序集以及引用程序集被改装饰(注解)描述了的类和接口
  3. 这里要注意注册的顺序,注册的顺序如果出错,就会爆出异常(本人已经经历过)
  4. 同时还需要注意,我们读取配置注册配置类必须是在最前的,因为配置加载最好是在程序启动前全部加载完(不过想想也有懒加载的情况,这里我没有难么多考虑)

代码实现

我这里加载文件配置的代码和注册类的代码写到了一起,有点耦合,大家看可用适当的做拆分,OK希望我的这个小工具类可用帮助到大家,如果大家有更好的想法,希望写出来文章来源地址https://www.toymoban.com/news/detail-746264.html

using gobangBack.Annotation;
using System;
using System.Reflection;

namespace gobangBack.Utils
{
    // 这个扩展方法仅仅对于本项目
    /// <summary>
    /// 步骤:
    /// 1.对于当前项目的Service目录下的所有带有Service结尾的类型进行父子关系判断
    /// 2.进行服务类型和实现类型的一次性注入
    /// </summary>
    public static class ServiceAutoDI
    {

        public static readonly  Queue<Type> RegisterQueue = new Queue<Type>();


        public static void AutoAllDI(this IServiceCollection service) {
            AutoServerDIFromService(service);
        }


        // 1.自动注册服务类
        public static void AutoServerDIFromService(this IServiceCollection service)
        {
            
             // 1.获取当前程序集中有被Server修饰过的所有的类(并且不能是抽象类)
             var classTypes = AppDomain.CurrentDomain.GetAssemblies()
                        .SelectMany(assembly => assembly.GetTypes())
                        .Where(type => type.IsClass && !type.IsAbstract)
                        .Where(type => Attribute.IsDefined(type, typeof(Server)))
                        .ToList();
            // 2.获得当前程序集中被Server修饰过的所有接口
            var interfaceTypes = AppDomain.CurrentDomain.GetAssemblies()
                        .SelectMany(assembly => assembly.GetTypes())
                        .Where(type => type.IsInterface)
                        .Where(type => Attribute.IsDefined(type, typeof(Server)))
                        .ToList();
            // 3.获取当前程序集中被Config修饰过的配置类
            var configClassTypes = AppDomain.CurrentDomain.GetAssemblies()
                        .SelectMany(assembly => assembly.GetTypes())
                        .Where(type => type.IsClass && !type.IsAbstract)
                        .Where(type => Attribute.IsDefined(type, typeof(Config)))
                        .ToList();



            // 3.判断类型的构造方法中是否有被Server修饰的接口或者是被Config修饰的类
            // 3.2获取到所有Server修饰类的构造函数中的所有参数
            var quoteInterface = classTypes
                .SelectMany(classType => classType.GetConstructors())
                .SelectMany(constructor => constructor.GetParameters())
            // 4.2 判断参数中是否有interfaceTypes的值,如果有,就将其找出放入注入队列中
                .Where(param => interfaceTypes.Contains(param.ParameterType))
                .Select(param => param.ParameterType).ToList();

            foreach (var interfaceType in quoteInterface)
            {
                RegisterQueue.Enqueue(interfaceType);
                interfaceTypes.Remove(interfaceType);
            }

            // 5.进行配置读取

            // 5.1.先加载好配置文件
            var configuration = new ConfigurationBuilder()
                .AddJsonFile("appsettings.json")
                .Build();

            // 5.2.进行配置文件的读取,配置的名称必须和类名一致
          
            configClassTypes.ForEach(config =>
            {
                // 1.获取到配置类结尾的部分
                string configName = config.FullName.Substring(config.FullName.LastIndexOf(".")+1);
                // 2.将配置类的配置添加到容器中
                // 2.1.获取到OptionsConfigurationServiceCollectionExtensions类中名称为Configure参数为IServiceCollection,IConfiguration的方法
                // 2.2.讲它的泛型类型设置config类型
                MethodInfo configureMethod = typeof(OptionsConfigurationServiceCollectionExtensions)
                    .GetMethod("Configure", new Type[] { typeof(IServiceCollection), typeof(IConfiguration) })
                    .MakeGenericMethod(config);
                // 3.读取配置文件中的名称为对应名称的部分,进行加载
                configureMethod.Invoke(null, new object[] { service, configuration.GetSection(configName) });

                // 4.注册配置类
                service.AddScoped(config);
            });

            // 6.优先注册在队列中的接口
            var prioityInterface = RegisterQueue.ToArray();

            foreach(var interfaceType in prioityInterface)
            {
               var implenmentTypes = classTypes.Where(classType => classType.IsAssignableTo(interfaceType))
                    .ToList();
                implenmentTypes.ForEach(type =>
                {
                    service.AddScoped(interfaceType, type);
                });
            }

            // 7.注册其它的接口类型
            foreach(var interfaceType in interfaceTypes)
            {
                var implenmentTypes = classTypes.Where(classType => classType.IsAssignableTo(interfaceType))
                    .ToList();
                implenmentTypes.ForEach(type =>
                {
                    service.AddScoped(interfaceType, type);
                });
            }
        }

    }
}


到了这里,关于C# 当前项目自动服务DI类的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Docker consul 容器服务自动发现和更新

    目录 一、什么是服务注册与发现 二、Docker-consul集群 1.Docker-consul consul提供的一些关键特性 2.registrator 3.Consul-template 三、Docker-consul实现过程 以配置nginx负载均衡为例 先配置consul-agent ,有两种模式server和client 四、Docker-consul集群配置 下载consul服务 常用启动选项 web服务器启动多

    2024年02月10日
    浏览(43)
  • Docker consul容器服务自动发现和更新

    目录 一、什么是服务注册与发现         二、Docker-consul集群 1.Docker-consul 2.registrator 3.Consul-template 三、Docker-consul实现过程 四、Docker-consul集群配置 1.下载consul服务 2.web服务器启动多例nginx容器,使用registrator自动发现 3.使用nginx做反向代理,使用Consul-template配置自动修改配

    2024年02月10日
    浏览(37)
  • 前端项目部署自动检测更新后通知用户刷新页面(前端实现,技术框架vue、js、webpack)——方案二:轮询去判断服务端的index.html是否跟当前的index.html的脚本hash值一样

    当我们重新部署前端项目的时候,如果用户一直停留在页面上并未刷新使用,会存在功能使用差异性的问题,因此,当前端部署项目后,需要提醒用户有去重新加载页面。 vue、js、webpack 根据打完包之后生成的 script src 的hash值去判断 ,每次打包都会生成唯一的hash值,只要轮

    2024年01月23日
    浏览(43)
  • Prometheus服务器、Prometheus被监控端、Grafana、监控MySQL数据库、自动发现概述、配置自动发现、Alertmanager

    目录 Prometheus概述 部署Prometheus服务器 环境说明: 配置时间 安装Prometheus服务器 添加被监控端 部署通用的监控exporter Grafana 概述 部署Grafana 展示node1的监控信息 监控MySQL数据库 配置MySQL 配置mysql exporter 配置mysql exporter 配置prometheus监控mysql 自动发现机制 概述 基于文件自动发现

    2024年02月21日
    浏览(59)
  • Docker-consul容器服务自动发现与注册

    docker consul 容器的自动发现与注册。 什么叫做微服务(容器)注册与发现 是一种分布式管理系统,定位服务的方法。 在传统架构中,应用程序之间直连到已知的服务,设备提供的网络:ip网络,基于tcp/ip:端口 由于现代微服务部署,服务的动态性,数量增加了,传统的基于

    2024年01月24日
    浏览(43)
  • springboot项目要如何获取当前服务器的IP以及当前项目使用的端口号Port

    使用InetAddress类即可,直接看例子: 在配置文件中配置server.port的值,之后通过@Value、@ConfigurationProperties 等方法从配置文件中获取 测试代码: @Value会导致启动报错,无法启动项目: 把@Value注释,启动正常,但是**@ConfigurationProperties获取到的值是0** 我们知道springboot默认的po

    2023年04月08日
    浏览(44)
  • golang云原生项目之:etcd服务注册与发现

    1直接调包 kitex-contrib: 上面有实现的案例,直接cv。下面是具体的理解 2 相关概念 EtcdResolver: etcd resolver是一种DNS解析器,用于将域名转换为etcd集群中的具体地址,以便应用程序可以与etcd集群进行通信。etcd是一个分布式键值存储系统,常用于服务发现、配置共享和分布式锁等

    2024年02月11日
    浏览(39)
  • QT-TCP客户端发现服务端掉线后如何自动重连接?

    在QT中,可以通过QTcpSocket类实现TCP客户端的网络连接,如果客户端断连后需要实现重连,可以在QTcpSocket的disconnected()信号处理槽中执行重连操作。具体实现步骤如下: 定义QTcpSocket实例变量,在构造函数中初始化并连接相应的信号和槽函数。 构造函数中初始化和连接相应的信

    2024年02月15日
    浏览(122)
  • Zabbix监控系统 第一部分:zabbix服务部署+自定义监控项+自动发现与自动注册(附详细部署实例)

    zabbix 是一个基于 Web 界面的提供分布式系统监视以及网络监视功能的企业级的开源解决方案。 zabbix 能监视各种网络参数,保证服务器系统的安全运营,提供灵活的通知机制以让系统管理员快速定位/解决存在的各种问题。 zabbix 由 2 部分构成,zabbix server 与可选组件 zabbix age

    2024年02月07日
    浏览(43)
  • C# webAPI 精解

    先创建一个web项目 基本可以运行的程度 用postman进行接口测试 .NET Framework 和 .NET Core 都可以创建 webAPI 这里用 .NET Framework 比较简单 。 启动 Visual Studio,并从“开始”页中选择“新建项目”。 或者,在 “文件” 菜单中,选择“ 新建 ”,然后选择“ 项目”。 在 “模板 ”窗格

    2024年02月09日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包