ASP.Net Core Web API单例服务重复实例化:如何调用已存在单例?
解决ASP.NET Core Web API中单例服务重复实例化的问题
我之前也踩过这个坑,明明注册了单例但每次请求都新建实例,大概率是几个常见的配置问题导致的,咱们一步步排查解决:
1. 先确认单例是否真的被重复实例化
别光凭业务逻辑的变化判断,先给你的MySingleton构造函数加个实例标识,直观验证是不是每次请求都生成了新实例:
public class MySingleton : IMySingleton { public MySingleton() { Console.WriteLine($"MySingleton 实例化,ID: {GetHashCode()}"); } public void MethodOfSingleton() { // 你的业务逻辑 } }
运行API后调用接口,如果控制台每次都输出新的ID,那确实是重复实例化了;如果ID不变,那可能是业务逻辑里的状态变化让你误以为是新实例,这时候就不用纠结DI的问题了。
2. 检查服务注册的正确性
(1)确保只注册一次单例,且生命周期正确
你在Startup.cs里写的services.AddSingleton<IMySingleton, MySingleton>()是正确的,但要检查:
- 有没有在其他地方(比如
Program.cs、其他模块的服务注册代码)重复注册这个服务?比如不小心写成了services.AddScoped<IMySingleton, MySingleton>()或者AddTransient,这会覆盖之前的单例注册,导致每次请求新建实例。 - 如果你用了自定义DI容器(比如Autofac),要确认容器的单例配置是否正确,有些第三方容器的单例规则和默认DI不一样。
(2)注册时机要正确
如果是.NET 6+的最小API模式,必须确保服务注册在builder.Build()之前完成,因为Build()之后DI容器就已经构建好了,再注册的服务不会生效:
var builder = WebApplication.CreateBuilder(args); // 必须在builder.Build()之前注册服务 builder.Services.AddSingleton<IMySingleton, MySingleton>(); builder.Services.AddControllers(); var app = builder.Build(); // 这里再注册服务就没用了!
3. 确保控制器被DI容器正确解析
你的控制器构造函数注入写法是对的,但要检查:
- 控制器有没有标记
[ApiController]?这个特性会告诉ASP.NET Core框架用DI容器来创建控制器实例,如果没加,框架可能会用无参构造函数(如果存在的话),这时候你注入的服务就不会生效,甚至可能报错。 - 有没有在路由配置或者其他地方手动实例化控制器?比如如果写了类似
app.MapGet("/my", () => new MyController(new MySingleton()).MyMethod()),这就完全绕开了DI,每次请求都会手动新建控制器和单例实例。
4. 检查单例服务是否被手动实例化
有没有在代码的其他地方直接new MySingleton()?比如在别的服务、工具类里手动创建实例,而不是通过注入IMySingleton获取,这会导致你拿到的不是DI容器管理的单例。
最后给个正确的示例
.NET 5及以前的Startup.cs写法
public class Startup { public void ConfigureServices(IServiceCollection services) { // 注册单例服务 services.AddSingleton<IMySingleton, MySingleton>(); services.AddControllers(); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { // 中间件配置... app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); } }
控制器写法
[ApiController] [Route("api/[controller]")] public class MyController : ControllerBase { private readonly IMySingleton _mySingleton; // 构造函数注入,框架自动从DI容器取单例 public MyController(IMySingleton mySingleton) { _mySingleton = mySingleton; Console.WriteLine($"控制器获取的单例ID: {_mySingleton.GetHashCode()}"); } [Route("[action]")] [HttpGet] public bool MyMethod() { try { _mySingleton.MethodOfSingleton(); return true; } catch (Exception) { return false; } } }
按照上面的步骤排查,90%的情况都能解决单例重复实例化的问题。
内容的提问来源于stack exchange,提问作者Nicolas.S
相关产品推荐
相关产品推荐

