ASP.NET Core 6+ 在 Program.cs 中通过 builder.Services 注册服务,推荐使用 AddSingleton、AddScoped(多数业务首选)、AddTransient;构造函数须为 public;多实现需用 IEnumerable 注入;IDbConnection 应工厂创建,HttpClient 须用 AddHttpClient;自定义服务依赖应通过工厂委托从 IServiceProvider 获取。
Program.cs 中如何注册服务ASP.NET Core 6+ 默认使用精简的 Program.cs 模式,服务注册直接在 var builder = WebApplication.CreateBuilder(args) 后调用 builder.Services。这是唯一推荐的入口点,别在 Startup.cs(已

常见注册方式有三类,区别在于生命周期管理:
AddSingleton() :整个应用生命周期共用一个实例,适合无状态工具类、配置读取器AddScoped() :每个 HTTP 请求创建一次,跨中间件/控制器复用,**绝大多数业务服务应选这个**AddTransient() :每次注入都新建实例,适合轻量、无共享状态的类(如 DTO 映射器)示例:
var builder = WebApplication.CreateBuilder(args); builder.Services.AddSingleton(builder.Configuration); builder.Services.AddScoped (); builder.Services.AddTransient ();
构造函数必须是 public,否则运行时抛出 InvalidOperationException: Unable to resolve service。.NET DI 容器只识别 public 构造函数。
同一接口注册多个实现时,默认只取最后一个——除非你明确使用集合注册:
AddScoped() 多次注册 → 只生效最后一次AddScoped() + AddScoped() → 仍只取最后注册的builder.Services.AddScoped(); builder.Services.AddScoped(); ,然后在构造函数中接收 IEnumerable
这样容器会自动聚合所有已注册的 IMessageHandler 实现。
IDbConnection 或 HttpClient 怎么办这些类型不能直接注册为单例或作用域服务,原因不同:
IDbConnection:是“即用即开即关”的资源,注册为 Scoped 会导致连接被跨请求复用,引发 InvalidOperation: Connection is already in use。应改为工厂模式或在 Repository 内部用 new SqlConnection(...) 创建HttpClient:官方强烈建议用 AddHttpClient() 注册,而不是 AddScoped() 。后者易导致端口耗尽(socket exhaustion),因为 HttpClient 本身是线程安全且设计为长期复用的,但底层 HttpMessageHandler 需要按需管理生命周期正确写法:
builder.Services.AddHttpClient() .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler { ServerCertificateCustomValidationCallback = (msg, cert, chain, err) => true });
IConfiguration 或 IWebHostEnvironment 怎么办不要在构造函数里试图“手动 new 自定义服务”,这会绕过 DI 容器,导致依赖链断裂。正确方式是让容器帮你传参:
AddScoped(sp => new RedisCacheService(sp.GetRequiredService()))
sp.GetRequiredService<...>() 获取其他已注册服务config 变量),必须从 IServiceProvider 获取,否则可能拿到错误作用域的实例特别提醒:IConfiguration 和 IWebHostEnvironment 是 Singleton,可放心在任何生命周期的服务中注入;但反过来,Scoped 服务不能注入到 Singleton 类的构造函数中,否则启动时报错。