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();}关键点说明反射扫描通过Assembly.GetEntryAssembly()获取主程序集,并递归加载所有引用的程序集,确保扫描到所有服务实现。
生命周期处理
瞬时(Transient):每次请求创建新实例。
作用域(Scoped):每个HTTP请求内共享实例。
单例(Singleton):整个应用生命周期共享实例。(注:示例中未直接处理Scoped的请求级生命周期,如需精确控制,可扩展Register方法。)
接口与实现分离服务实现类可以同时实现多个接口(如ITestService和ITransient),自动注册时会将所有接口绑定到实现类。
直接注册实现类扩展方法中register(impl, impl)允许直接通过实现类类型解析服务(如services.AddTransient<TestService>())。
通过此方法,可以高效实现.NET6 WebApi的自动依赖注入,保持代码简洁且易于扩展。