如何在.NET6 WebApi中实现自动依赖注入

大哥大姐,哪位知道,如何在.NET6 WebApi中实现自动依赖注入
最新回答
梦他

2026-10-30 08:38:56

在.NET6 WebApi中实现自动依赖注入,可以通过反射机制扫描程序集,自动注册实现了特定生命周期接口的服务。以下是详细实现步骤:

1. 定义生命周期标记接口

创建三个接口,分别对应依赖注入的三种生命周期:

// 瞬时生命周期接口public interface ITransient { }// 作用域生命周期接口public interface IScoped { }// 单例生命周期接口public interface ISingleton { }2. 实现自动注册扩展方法

通过反射扫描程序集,自动注册实现了生命周期接口的服务:

using System.Reflection;public static class ServiceCollectionExtensions{ public static IServiceCollection RegisterAllServices(this IServiceCollection services) { // 获取当前程序集及其引用的所有程序集 var entryAssembly = Assembly.GetEntryAssembly(); var types = entryAssembly!.GetReferencedAssemblies() .Select(Assembly.Load) .Concat(new[] { entryAssembly }) .SelectMany(x => x.GetTypes()) .Distinct(); // 分别注册三种生命周期的服务 Register<ITransient>(types, services.AddTransient); Register<IScoped>(types, services.AddScoped); Register<ISingleton>(types, services.AddSingleton); return services; } private static void Register<TLifetime>( IEnumerable<Type> types, Func<Type, Type, IServiceCollection> register) { // 找到所有实现了TLifetime接口的具体类 var implementations = types.Where(x => x.IsClass && !x.IsAbstract && x.GetInterfaces().Contains(typeof(TLifetime))); foreach (var impl in implementations) { // 获取服务实现的所有接口(排除生命周期接口) var interfaces = impl.GetInterfaces() .Where(i => i != typeof(TLifetime)); // 以每个接口为服务契约注册实现 foreach (var iface in interfaces) { register(iface, impl); } // 直接注册实现类本身(可选) register(impl, impl); } }}3. 在Program.cs中启用自动注册

在创建WebApplication后调用扩展方法:

var builder = WebApplication.CreateBuilder(args);// 自动注册所有服务builder.Services.RegisterAllServices();// 其他服务配置builder.Services.AddControllers();builder.Services.AddEndpointsApiExplorer();builder.Services.AddSwaggerGen();var app = builder.Build();// ... 配置中间件app.Run();4. 服务实现示例

通过继承生命周期接口标记服务,无需手动注册:

// 服务接口public interface ITestService{ int GetValue();}// 服务实现(瞬时生命周期)public class TestService : ITestService, ITransient{ public int GetValue() => 123;}5. 在控制器中使用

通过构造函数注入服务:

[ApiController][Route("[controller]")]public class TestController : ControllerBase{ private readonly ITestService _testService; public TestController(ITestService testService) { _testService = testService; } [HttpGet] public int Get() => _testService.GetValue();}关键点说明
  1. 反射扫描通过Assembly.GetEntryAssembly()获取主程序集,并递归加载所有引用的程序集,确保扫描到所有服务实现。

  2. 生命周期处理

    瞬时(Transient):每次请求创建新实例。

    作用域(Scoped):每个HTTP请求内共享实例。

    单例(Singleton):整个应用生命周期共享实例。(注:示例中未直接处理Scoped的请求级生命周期,如需精确控制,可扩展Register方法。)

  3. 接口与实现分离服务实现类可以同时实现多个接口(如ITestService和ITransient),自动注册时会将所有接口绑定到实现类。

  4. 直接注册实现类扩展方法中register(impl, impl)允许直接通过实现类类型解析服务(如services.AddTransient<TestService>())。

优势
  • 减少样板代码:避免在Program.cs中逐个注册服务。
  • 维护性:新增服务只需添加生命周期标记接口,无需修改启动配置。
  • 灵活性:支持多接口绑定和直接注册实现类。
注意事项
  1. 性能影响:反射扫描在启动时执行,对性能影响微乎其微。
  2. 程序集范围:确保服务实现类位于主程序集或其引用的程序集中。
  3. 复杂场景:如需条件注册或更复杂的生命周期控制,仍需手动配置。

通过此方法,可以高效实现.NET6 WebApi的自动依赖注入,保持代码简洁且易于扩展。