当前位置: 首页 > article >正文

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

在这里插入图片描述

依赖注入配置变形

随着业务的增长,我们项目工作中的类型、服务越来越多,而每一个服务的依赖注入关系都需要在入口文件通过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.kler.cn/a/447255.html

相关文章:

  • BERT的改进:ModernBERT
  • 彻底认识和理解探索分布式网络编程中的SSL安全通信机制
  • OB删除1.5亿数据耗费2小时
  • 如何使用 WebAssembly 扩展后端应用
  • 【Prompt Engineering】6 文本扩展
  • Edge Scdn防御网站怎么样?
  • gesp(三级)(8)洛谷:B3926:[GESP202312 三级] 单位转换
  • HarmonyOS(71) 自定义事件分发之TouchTestStrategy使用说明
  • 电脑提示ntdll.d缺失是什么原因?不处理的话会怎么样?ntdll.dll文件缺失快速解决方案来啦!
  • 数据云平台的可观测性
  • 【Leecode】Leecode刷题之路第87天之扰乱字符串
  • SKETCHPAD——允许语言模型生成中间草图,在几何、函数、图算法和游戏策略等所有数学任务中持续提高基础模型的性能
  • ip_output函数
  • 音视频学习(二十六):http-flv
  • Docker搭建kafka环境
  • 线性分类器(KNN,SVM损失,交叉熵损失,softmax)
  • 微信小程序-生成骨架屏
  • nbcio-vue版本第一次登录出现404问题
  • Docker安全性与最佳实践
  • Hive其五,使用技巧,数据查询,日志以及复杂类型的使用
  • 【VSCode】常用插件汇总
  • linux应用编程(点亮LED)
  • VSCode 中 Git 功能比较:内置 Git、GitLens 与 Git History 插件
  • 腾讯游戏安全移动赛题Tencent2016A
  • gesp(二级)(8)洛谷:B3866:[GESP202309 二级] 数字黑洞
  • 云手机测评:云端赋能的智能移动新势力