ASP.NET Core 反射动态发现类库服务

文章目录


前言

ASP.NET Core 中,依赖注入(Dependency Injection, DI )是一种核心设计模式,用于管理对象的创建和生命周期,从而实现松耦合和可测试性

反射动态发现类库服务,适用于需要高度模块化的 ASP.NET Core 应用。

一、反射动态发现类库服务

1)定义公共接口(核心契约)

  1. 创建一个公共类库(例如 SharedContracts),定义服务注册的统一接口。所有其他类库需引用该库

  2. 引用包
    Install-Package Microsoft.Extensions.DependencyInjection
    Install-Package Microsoft.Extensions.Configuration

    csharp 复制代码
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Configuration;
    namespace SharedContracts
    {
        public interface IServiceRegistrar
        {
            //void RegisterServices(IServiceCollection services);
            void RegisterServices(IServiceCollection services, IConfiguration configuration);
        }
    }

2)类库实现服务注册逻辑

  1. 每个类库需实现 IServiceRegistrar 接口,封装自身的服务注册代码。

  2. 示例数据访问层类库 (DataAccess)
    引用包
    Install-Package Microsoft.Extensions.Configuration
    Install-Package Microsoft.Extensions.DependencyInjection
    Install-Package Microsoft.Extensions.DependencyInjection.Abstractions
    Install-Package Microsoft.EntityFrameworkCore.SqlServer

    csharp 复制代码
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using SharedContracts;
    using Microsoft.EntityFrameworkCore;
    
    namespace DataAccess
    {
        public class DataAccessServiceRegistrar : IServiceRegistrar
        {
            public void RegisterServices(IServiceCollection services, IConfiguration configuration)
            {
                // 注册 DbContext
                services.AddDbContext<AppDbContext>(options =>
                    options.UseSqlServer(configuration.GetConnectionString("DefaultConnection")));
    
                // 注册其他服务
                //services.AddScoped<IUserRepository, UserRepository>();
            }
        }
    }
  3. 示例业务逻辑层类库 (BusinessLogic)
    引用包
    Install-Package Microsoft.Extensions.DependencyInjection
    Install-Package Microsoft.Extensions.Configuration

    csharp 复制代码
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using SharedContracts;
    
    namespace BusinessLogic
    {
        public class BusinessLogicServiceRegistrar : IServiceRegistrar
        {
            public void RegisterServices(IServiceCollection services, IConfiguration configuration)
            {
                // 注册业务服务
                services.AddScoped<IUserService, UserServiceImpl>();
                services.AddScoped<IOrderService, OrderServiceImpl>();
            }
        }
    }

3)主程序动态加载注册逻辑

  1. ASP.NET Core 主项目的 Program.cs 中,使用反射扫描所有程序集,自动发现并执行注册。

    csharp 复制代码
    using System.Reflection;
    using SharedContracts;
    
    var builder = WebApplication.CreateBuilder(args);
    
    // 动态加载所有类库的注册逻辑
    LoadServiceRegistrars(builder.Services, builder.Configuration);
    
    var app = builder.Build();
    app.Run();
    
    // 反射扫描方法
    static void LoadServiceRegistrars(IServiceCollection services, IConfiguration configuration)
    {
        // 获取所有已加载的程序集(可根据项目前缀过滤)
        var assemblies = AppDomain.CurrentDomain.GetAssemblies()
            .Where(a => a.FullName!.StartsWith("YourProjectPrefix")); 
    
        foreach (var assembly in assemblies)
        {
            // 查找所有实现 IServiceRegistrar 的非抽象类
            var registrarTypes = assembly.GetTypes()
                .Where(t => 
                    typeof(IServiceRegistrar).IsAssignableFrom(t) && 
                    !t.IsAbstract && 
                    !t.IsInterface);
    
            foreach (var type in registrarTypes)
            {
                // 创建实例并调用注册方法
                if (Activator.CreateInstance(type) is IServiceRegistrar registrar)
                {
                    registrar.RegisterServices(services, configuration);
                }
            }
        }
    }

4)解决程序集未加载问题

  1. 若类库未被主程序直接引用,需确保程序集被加载到当前域。可在主程序中添加以下代码强制加载。

    csharp 复制代码
    // 手动加载特定类库程序集(可选)
    var dataAccessAssembly = Assembly.Load("DataAccess");
    var businessLogicAssembly = Assembly.Load("BusinessLogic");

二、注意事项

1)性能优化

  1. 限制扫描的程序集范围(如通过 StartsWith("YourProjectPrefix")),避免扫描系统程序集。
  2. 缓存扫描结果(如使用静态变量),避免每次启动重复扫描。

2)依赖传递

  1. 确保类库引用了 SharedContracts
  2. 确保必要的 NuGet 包(如 Microsoft.Extensions.DependencyInjection等)。

3)配置隔离

  1. 每个类库的 IServiceRegistrar 实现应仅注册自身服务,避免操作其他类库的配置

4)异常处理

  1. 添加 try-catch 块处理反射过程中的潜在错误(如类型加载失败)。

适用场景

  1. 大型分布式系统,服务按模块拆分到不同类库。
  2. 插件化架构,允许动态加载/卸载功能模块。
  3. 需要严格解耦主程序和类库的项目。
相关推荐
今天背单词了吗9802 分钟前
算法学习笔记:8.Bellman-Ford 算法——从原理到实战,涵盖 LeetCode 与考研 408 例题
java·开发语言·后端·算法·最短路径问题
天天摸鱼的java工程师5 分钟前
使用 Spring Boot 整合高德地图实现路线规划功能
java·后端
阿杆7 分钟前
😡同事查日志太慢,我现场教他一套 grep 组合拳!
linux·后端
PetterHillWater7 分钟前
基于Trae智能复杂项目重构实践
后端·aigc
凌览21 分钟前
有了 25k Star 的MediaCrawler爬虫库加持,三分钟搞定某红书、某音等平台爬取!
前端·后端·python
这里有鱼汤32 分钟前
给你的DeepSeek装上实时行情,让他帮你炒股
后端·python·mcp
咖啡啡不加糖35 分钟前
暴力破解漏洞与命令执行漏洞
java·后端·web安全
风象南38 分钟前
SpringBoot敏感配置项加密与解密实战
java·spring boot·后端
ん贤1 小时前
RESTful风格
后端·go·restful
Humbunklung1 小时前
Rust方法语法:赋予结构体行为的力量
开发语言·后端·rust