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. 需要严格解耦主程序和类库的项目。
相关推荐
饕餮争锋2 小时前
Spring Boot Starter简介-笔记
spring boot·笔记·后端
字节源流3 小时前
springboot单体项目的执行流程
java·spring boot·后端
豌豆花下猫12 小时前
uv全功能更新:统一管理Python项目、工具、脚本和环境的终极解决方案
后端·python·ai
深度物联网13 小时前
Spring Boot多模块划分设计
java·spring boot·后端
YUELEI11814 小时前
spring cloud 与 cloud alibaba 版本对照表
后端·spring·spring cloud
小杜-coding17 小时前
黑马点评day02(缓存)
java·spring boot·redis·后端·spring·maven·mybatis
程序员小刚18 小时前
基于SpringBoot + Vue 的火车票订票系统
vue.js·spring boot·后端
fanTuanye20 小时前
【SpringBoot篇】详解短信验证码登录功能实现
spring boot·后端
DonciSacer20 小时前
第一章-Rust入门
开发语言·后端·rust
西京刀客20 小时前
golang常用库之-标准库text/template
开发语言·后端·golang