用途
该技能面向使用 Microsoft.Extensions.DependencyInjection 的 .NET 应用,提供依赖注入(DI)的模式与最佳实践。核心目标是解决服务注册缺乏组织的问题:当所有注册都堆在 Program.cs/Startup.cs 中时,会出现难以查找相关注册、子系统之间边界不清、测试无法复用配置、团队协作时合并冲突频繁、内部依赖无法封装等问题。
主要能力
- 扩展方法组合:将相关服务注册分组到扩展方法中,例如 AddUserServices()、AddOrderServices()、AddEmailServices()、AddPaymentServices()、AddValidators(),使 Program.cs 保持简洁且可组合。
- 配置绑定:在扩展方法中通过 AddOptions<T>().BindConfiguration(...).ValidateDataAnnotations().ValidateOnStart() 绑定配置节。
- 分层扩展:对大型应用按层级组合扩展,如 AddAppServices() 调用 AddDomainServices()、AddInfrastructureServices()、AddApiServices()。
- 条件注册:根据 IHostEnvironment 判断环境,在开发环境与生产环境注册不同的实现(如 MailpitEmailSender 与 SmtpEmailSender)。
- 工厂式注册:对初始化复杂的服务使用工厂委托注册,从 IServiceProvider 解析所需选项与日志器。
- 键控服务(.NET 8+):使用 AddKeyedSingleton 注册多个同接口实现,并通过键区分(如 email、sms、push)。
- 生命周期管理:区分 Singleton、Scoped、Transient 的适用场景,并说明作用域要求。
- 测试复用:在 WebApplicationFactory、Akka.Hosting.TestKit 及独立单元测试中复用生产环境的 Add* 扩展,仅覆盖需要替换的外部依赖。
- Akka.Hosting 集成:同样的扩展方法模式可用于 Akka.NET 的 actor 配置(如 AddOrderActors())。
使用方式
- 为每个功能模块创建 {Feature}ServiceCollectionExtensions.cs 静态类,放在其注册的服务附近。
- 在扩展方法中注册该模块的仓储、服务、选项等,并返回 IServiceCollection 以支持链式调用。
- 在 Program.cs 中依次调用各 Add* 方法组合出完整配置。
- 需要配置时,让扩展方法接收配置节名称或连接字符串等参数,避免硬编码。
- 测试时复用生产扩展,仅用 RemoveAll<T>() 移除并替换需要模拟的外部依赖。
命名约定:Add{Feature}Services() 用于一般功能注册;Add{Feature}() 用于无歧义的短形式;Configure{Feature}() 用于主要设置选项;Use{Feature}() 用于 IApplicationBuilder 上的中间件。
适用场景
- ASP.NET Core 应用中组织服务注册。
- 避免 Program.cs/Startup.cs 出现数百行注册代码。
- 让服务配置在生产与测试之间复用。
- 设计可与 Microsoft.Extensions.DependencyInjection 集成的库。
- 后台服务与 Akka.NET actor 中需要手动创建作用域的场景。
限制与注意事项
- 作用域服务需要存在作用域:ASP.NET Core 每个 HTTP 请求自动创建作用域,但后台服务、actor 等上下文需注入 IServiceProvider 并手动调用 CreateScope()。
- 避免反模式:不要在 Program.cs 中注册所有内容;不要创建过于笼统的扩展(如 AddServices() 注册大量不相关内容);不要在扩展中隐藏重要配置(如硬编码连接字符串),应显式接收配置参数。
- 生命周期选择需谨慎:Singleton 用于无状态、线程安全、创建成本高的服务;Scoped 用于每请求有状态的服务与数据库上下文;Transient 用于轻量、短生命周期、创建成本低的服务。
- 关于该技能的具体安装命令、收费方式、支持平台等信息,资料中暂未提供。