.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)
            );
    }
}

640

 


注册特性(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

如果你还在为一堆 AddScopedAddTransient 头疼,Injectio 会是你的救星!

posted @ 2025-10-13 08:38  酒醉后的疯言疯语  阅读(32)  评论(0)    收藏  举报