如何在中间件、控制器与后台服务间共享Singleton实例?
嘿,我来帮你搞定这个问题!你已经成功注册了ConcurrentQueue<string>的单例服务,要在中间件里访问它其实有两种很实用的方式,下面我给你详细说明:
方法1:自定义中间件类通过构造函数注入
这种方式适合逻辑相对复杂的中间件,也是比较规范的做法。你可以创建一个自定义中间件类,直接在构造函数里注入ConcurrentQueue<string>实例:
public class DataWritingMiddleware { private readonly RequestDelegate _next; private readonly ConcurrentQueue<string> _sharedQueue; // 构造函数注入已注册的ConcurrentQueue单例 public DataWritingMiddleware(RequestDelegate next, ConcurrentQueue<string> sharedQueue) { _next = next; _sharedQueue = sharedQueue; } public async Task InvokeAsync(HttpContext context) { // 在这里就可以直接操作队列写入数据了 _sharedQueue.Enqueue($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] 中间件写入的数据"); // 别忘了调用后续中间件,保证请求管道正常流转 await _next(context); } }
之后在Program.cs(或者Startup.cs的Configure方法)里注册这个中间件就行:
app.UseMiddleware<DataWritingMiddleware>();
方法2:内联中间件通过RequestServices获取
如果你的中间件逻辑很简单,不想单独写一个类,也可以直接在app.Use()里通过HttpContext的请求服务来获取单例:
app.Use(async (context, next) => { // 从RequestServices中获取已注册的ConcurrentQueue实例 var sharedQueue = context.RequestServices.GetService<ConcurrentQueue<string>>(); if (sharedQueue != null) { sharedQueue.Enqueue($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] 内联中间件写入的数据"); } // 继续执行后续请求管道 await next(); });
补充说明
- 你之前注册单例的代码是没问题的,再确认下:
ConcurrentQueue<string> sharedData = new ConcurrentQueue<string>(); services.AddSingleton(typeof(ConcurrentQueue<string>), sharedData); - 因为
ConcurrentQueue本身是线程安全的,所以不管是中间件、控制器还是后台服务,并发读写都不用额外加锁,放心用就行。
内容的提问来源于stack exchange,提问作者Sandy
相关产品推荐
相关产品推荐

