当前位置: 首页 > news >正文

.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 会是你的救星!

http://www.hskmm.com/?act=detail&tid=29822

相关文章:

  • VLA技术论文阅读 - 详解
  • 深入解析:246-基于Django的美食菜谱数据分析推荐系统
  • PhotoShop网页版在线为图片加文字,制作个性海报教程
  • 简单高效的SQL注入测试方法:Break Repair技巧详解
  • display ip interface brief 概念及题目 - 指南
  • VMware ESXi 9.0.1.0 macOS Unlocker OEM BIOS 2.7 HPE 慧与 定制版
  • VMware ESXi 9.0.1.0 macOS Unlocker OEM BIOS 2.7 Lenovo 联想 定制版
  • 当AI开始“通感”:诗词创作中的灵性涌现
  • VMware ESXi 9.0.1.0 macOS Unlocker OEM BIOS 2.7 Dell 戴尔 定制版
  • 【GitHub每日速递 251013】SurfSense:可定制AI研究神器,连接多源知识,功能超丰富!
  • FileZilla Client升级之后报了一个错误queue.sqlite3文件保存失败
  • tap issue
  • 通配符SSL证书价格对比 iTrustSSL与RapidSSL哪个更有优势?
  • 降低网络保险成本的实用技巧与网络安全实践
  • 自动评估对话质量的AI技术突破
  • 4.2 基于模型增强的无模型强化学习(Model-based Augmented Model-free RL)
  • 乐理 -07 和弦, 和声
  • 4.1 基于模型的强化学习(Model-based RL)
  • 3.8 最大熵强化学习(Maximum Entropy RL, SAC)
  • 乐理 -06 和弦, 和声
  • 3.7 带经验回放的演员–评论家算法(Actor-Critic with Experience Replay, ACER)
  • 3.6 策略优化(TRPO 与 PPO)
  • 3.5 自然梯度(Natural Gradients)
  • 3.3 离策略演员–评论家(Off-policy Actor–Critic)
  • 3.4 深度确定性策略梯度(Deep Deterministic Policy Gradient, DDPG)
  • 20232325 2025-2026-1 《网络与系统攻防技术》实验一实验报告
  • 乐理 -06 相对音感 绝对音感
  • 【光照】UnityURP[天空盒]原理与[动态天空盒]实现
  • Hadoop概念以及安装
  • Presto