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. 需要严格解耦主程序和类库的项目。
相关推荐
Y***h1875 小时前
第二章 Spring中的Bean
java·后端·spring
稚辉君.MCA_P8_Java5 小时前
DeepSeek 插入排序
linux·后端·算法·架构·排序算法
t***p9356 小时前
idea创建SpringBoot自动创建Lombok无效果(解决)
spring boot·后端·intellij-idea
d***81726 小时前
解决SpringBoot项目启动错误:找不到或无法加载主类
java·spring boot·后端
无限大66 小时前
RBAC模型:像电影院选座一样管理权限,告别"一个用户配一个权限"的噩梦
后端
间彧6 小时前
在CI/CD流水线中如何集成自动化的发布验证和熔断机制?
后端
间彧6 小时前
如何处理蓝绿部署中的数据迁移和数据库版本兼容性问题?
后端
间彧6 小时前
什么是金丝雀/灰度发布
后端
间彧6 小时前
什么是蓝绿部署
后端
爷_7 小时前
Golang: sqlc 和 goose 最佳实践
后端·go·全栈