百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

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

bigegpt 2024-08-15 20:01 2 浏览

思路

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

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

步骤如下:

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



代码实现

我这里加载文件配置的代码和注册类的代码写到了一起,有点耦合,大家看可用适当的做拆分,OK希望我的这个小工具类可用帮助到大家,如果大家有更好的想法,希望写出来

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);
                });
            }
        }
 
    }
}
 





相关推荐

了解Linux目录,那你就了解了一半的Linux系统

大到公司或者社群再小到个人要利用Linux来开发产品的人实在是多如牛毛,每个人都用自己的标准来配置文件或者设置目录,那么未来的Linux则就是一团乱麻,也对管理造成许多麻烦。后来,就有所谓的FHS(F...

Linux命令,这些操作要注意!(linux命令?)

刚玩Linux的人总觉得自己在演黑客电影,直到手滑输错命令把公司服务器删库,这才发现命令行根本不是随便乱用的,而是“生死簿”。今天直接上干货,告诉你哪些命令用好了封神!喜欢的一键三连,谢谢观众老爷!!...

Linux 命令速查手册:这 30 个高频指令,拯救 90% 的运维小白!

在Linux系统的世界里,命令行是强大的武器。对于运维小白而言,掌握一些高频使用的Linux命令,能极大提升工作效率,轻松应对各种系统管理任务。今天,就为大家奉上精心整理的30个Linu...

linux必学的60个命令(linux必学的20个命令)

以下是Linux必学的20个基础命令:1.cd:切换目录2.ls:列出文件和目录3.mkdir:创建目录4.rm:删除文件或目录5.cp:复制文件或目录6.mv:移动/重命名文件或目录7....

提高工作效率的--Linux常用命令,能够决解95%以上的问题

点击上方关注,第一时间接受干货转发,点赞,收藏,不如一次关注评论区第一条注意查看回复:Linux命令获取linux常用命令大全pdf+Linux命令行大全pdf为什么要学习Linux命令?1、因为Li...

15 个实用 Linux 命令(linux命令用法及举例)

Linux命令行是系统管理员、开发者和技术爱好者的强大工具。掌握实用命令不仅能提高效率,还能解锁Linux系统的无限潜力,本文将深入介绍15个实用Linux命令。ls-列出目录内容l...

Linux 常用命令集合(linux常用命令全集)

系统信息arch显示机器的处理器架构(1)uname-m显示机器的处理器架构(2)uname-r显示正在使用的内核版本dmidecode-q显示硬件系统部件-(SMBIOS/DM...

Linux的常用命令就是记不住,怎么办?

1.帮助命令1.1help命令#语法格式:命令--help#作用:查看某个命令的帮助信息#示例:#ls--help查看ls命令的帮助信息#netst...

Linux常用文件操作命令(linux常用文件操作命令有哪些)

ls命令在Linux维护工作中,经常使用ls这个命令,这是最基本的命令,来写几条常用的ls命令。先来查看一下使用的ls版本#ls--versionls(GNUcoreutils)8.4...

Linux 常用命令(linux常用命令)

日志排查类操作命令查看日志cat/var/log/messages、tail-fxxx.log搜索关键词grep"error"xxx.log多条件过滤`grep-E&#...

简单粗暴收藏版:Linux常用命令大汇总

号主:老杨丨11年资深网络工程师,更多网工提升干货,请关注公众号:网络工程师俱乐部下午好,我的网工朋友在Linux系统中,命令行界面(CLI)是管理员和开发人员最常用的工具之一。通过命令行,用户可...

「Linux」linux常用基本命令(linux常用基本命令和用法)

Linux中许多常用命令是必须掌握的,这里将我学linux入门时学的一些常用的基本命令分享给大家一下,希望可以帮助你们。总结送免费学习资料(包含视频、技术学习路线图谱、文档等)1、显示日期的指令:d...

Linux的常用命令就是记不住,怎么办?于是推出了这套教程

1.帮助命令1.1help命令#语法格式:命令--help#作用:查看某个命令的帮助信息#示例:#ls--help查看ls命令的帮助信息#netst...

Linux的30个常用命令汇总,运维大神必掌握技能!

以下是Linux系统中最常用的30个命令,精简版覆盖日常操作核心需求,适合快速掌握:一、文件/目录操作1.`ls`-列出目录内容`ls-l`(详细信息)|`ls-a`(显示隐藏文件)...

Linux/Unix 系统中非常常用的命令

Linux/Unix系统中非常常用的命令,它们是进行文件操作、文本处理、权限管理等任务的基础。下面是对这些命令的简要说明:**文件操作类:*****`ls`(list):**列出目录内容,显...