.NET 自动依赖注入神器
在 .NET Core/Web 项目中,手动写一堆 services.AddScoped<...>
、AddSingleton<...>
是否让你头大?今天给大家介绍一个神器——Injectio,帮你自动扫描并注册服务,减少重复代码,让你的依赖注入(DI)更加优雅。
什么是 Injectio?
Injectio
是一个 自动服务注册库,通过 约定(Convention)+ 特性(Attribute) 自动扫描并注册依赖服务。
简单理解:
- • 不用手动注册服务
- • 支持 Singleton / Scoped / Transient
- • 支持工厂方法、模块注册、泛型和 Keyed 服务
适用于 .NET 6/7/8 Web 或控制台项目。
安装
dotnet add package Injectio
或者添加到 .csproj
文件中
<PackageReference Include="Injectio" PrivateAssets="all" />
PrivateAssets="all"
表示这个包不会被依赖它的项目引用。
基础用法
1️⃣ 创建接口和实现类
public interfaceIMessageService { string Send(string message); } [RegisterSingleton] // 自动注册为单例 publicclassEmailMessageService : IMessageService { public string Send(string message) { Console.WriteLine($"Email sent: {message}"); return message; } }
2️⃣ 在入口程序中调用 Injectio
对于 .NET 6/7/8 最小 API:
using Injectio; var builder = WebApplication.CreateBuilder(args); // 👈 自动注册项目中的服务(自动生成的)类,可以看截图 builder.Services.AddInjectioDemo(); var app = builder.Build(); app.MapGet("/", (IMessageService messageService) => { messageService.Send("Hello from Injectio!"); return"Message sent!"; }); app.Run();
或者在控制器中使用
[ApiController] [Route("[controller]/[action]")] publicclassWeatherForecastController : ControllerBase { privatereadonly IMessageService _myService; public WeatherForecastController(IMessageService myService) { _myService = myService; } [HttpGet(Name = "GetWeatherForecast2")] public string Get2() { return _myService.Send("Hello from WeatherForecastController!"); } }
这样就不用再写
services.AddScoped<IMessageService, EmailMessageService>()
了!
方法注册
public class RegistrationModule { [RegisterServices] public static void Register(IServiceCollection services) { services .AddOptions<PollingOption>() .Configure<IConfiguration>((settings, configuration) => configuration.GetSection(PollingOption.SectionName).Bind(settings) ); } }

注册特性(Attributes)
在类上添加注册特性,源生成器会自动发现并注册服务。
特性 | 说明 |
[RegisterSingleton] |
标记为单例服务 |
[RegisterScoped] |
标记为作用域服务 |
[RegisterTransient] |
标记为瞬态服务 |
[RegisterServices] |
标记方法,用于注册服务 |
特性可选属性
ServiceType
:指定注册接口ImplementationType
:指定实现类型Factory
:使用工厂方法创建实例Duplicate
:重复注册策略(Skip / Replace / Append)Registration
:注册策略(Self / ImplementedInterfaces / SelfWithInterfaces)
重复注册策略
Skip
:已存在的服务跳过注册Replace
:替换已有的服务注册Append
:在已有服务后追加注册
注册策略
Self
:将具体类型注册为自身ImplementedInterfaces
:注册为其实现的接口SelfWithInterfaces
:注册为自身及实现的接口
示例
单例服务
[RegisterSingleton] public class SingletonService : IService { }
指定服务类型:
[RegisterSingleton(ServiceType = typeof(IService))] public class SingletonService : IService { }
支持 IEnumerable<T>
多服务解析:
[RegisterSingleton(Duplicate = DuplicateStrategy.Append)] public class SingletonService : IService { }
作用域服务
[RegisterScoped] public class ScopedService : IService { }
瞬态服务
[RegisterTransient] public class TransientService : IService { }
工厂注册
[RegisterTransient(Factory = nameof(ServiceFactory))] publicclassFactoryService : IFactoryService { privatereadonly IService _service; public FactoryService(IService service) { _service = service; } public static IFactoryService ServiceFactory(IServiceProvider serviceProvider) { returnnew FactoryService(serviceProvider.GetService<IService>()); } }
开放泛型(Open Generic)
[RegisterSingleton(ImplementationType = typeof(OpenGeneric<>), ServiceType = typeof(IOpenGeneric<>))] public class OpenGeneric<T> : IOpenGeneric<T> { }
版本 5.0+ 支持自注册开放泛型:
[RegisterSingleton] public class OpenGeneric<T> : IOpenGeneric<T> { }
泛型特性(需 .NET 7.0+)
[RegisterSingleton<IService>] public class ServiceImplementation : IService { }
Keyed 服务(需 Microsoft.Extensions.DependencyInjection 8.0+)
[RegisterSingleton<IServiceKeyed>(ServiceKey = "Alpha")] public class ServiceAlphaKeyed : IServiceKeyed { } [RegisterSingleton<IServiceKeyed>(ServiceKey = "Beta")] public class ServiceBetaKeyed : IServiceKeyed { }
使用枚举注册:
public enum ServiceType { Alpha, Beta } [RegisterSingleton<IServiceKeyed>(ServiceKey = ServiceType.Alpha)] public class ServiceAlphaTypeKeyed : IServiceKeyed { } [RegisterSingleton<IServiceKeyed>(ServiceKey = ServiceType.Beta)] public class ServiceBetaTypeKeyed : IServiceKeyed { }
使用工厂方法注册:
[RegisterSingleton<IServiceKeyed>(ServiceKey = "Charlie", Factory = nameof(ServiceFactory))] [RegisterSingleton<IServiceKeyed>(ServiceKey = "Delta", Factory = nameof(ServiceFactory))] public class ServiceFactoryKeyed : IServiceKeyed { public ServiceFactoryKeyed(object? serviceKey) { ServiceKey = serviceKey; } public object? ServiceKey { get; } public static IServiceKeyed ServiceFactory(IServiceProvider serviceProvider, object? serviceKey) { return new ServiceFactoryKeyed(serviceKey); } }
添加到容器
源生成器会生成一个扩展方法,将所有发现的服务注册到容器中:
var services = new ServiceCollection(); services.AddInjectioTestsConsole();
自定义扩展方法名称(通过 MSBuild 属性 InjectioName
):
<PropertyGroup> <InjectioName>Library</InjectioName> </PropertyGroup> <ItemGroup> <CompilerVisibleProperty Include="InjectioName" /> </ItemGroup>
使用方法:
var services = new ServiceCollection(); services.AddLibrary();
注册标签(Tags)
标记服务:
public interface IServiceTag { } [RegisterSingleton(Tags = "Client,FrontEnd")] public class ServiceTag : IServiceTag { }
在注册方法中使用标签:
public static class ServiceRegistration { [RegisterServices] public static void Register(IServiceCollection services, ISet<string> tags) { // 根据 tags 条件注册服务 } }
添加到容器时指定标签(不指定则注册所有服务):
var services = new ServiceCollection(); services.AddInjectioTestsLibrary("Client");
💡 总结
Injectio
让 .NET 项目的依赖注入变得自动化、优雅,同时支持:
- • 多种生命周期:Singleton / Scoped / Transient
- • 工厂、模块、泛型、Keyed 服务
- • 标签控制和重复策略
- • 最小化手动注册,减少 boilerplate
如果你还在为一堆 AddScoped
、AddTransient
头疼,Injectio 会是你的救星!
本文来自博客园,作者:酒醉后的疯言疯语,转载请注明原文链接:https://www.cnblogs.com/Andy-Blog/p/19137665