使用 Scoped Service 的 Websocket 单例

Websocket singleton who uses Scoped Service

我已经实现了 WebSocket 中间件,它包含作为字段的单例 WebSocket 字典(通过构造函数注入)和一些其他通过构造函数注入的作用域参数。

我想知道它是否正确实施。

public WebSocketManagerMiddleware(RequestDelegate next,
    IWebSocketConnectionDictionary webSocketDictionary,
    IScopedServiceOne scopedOneService, IScopedServiceTwo scopedtwoService)
{
    _next = next;
    _webSocketManager = webSocketDictionary;
    _scopedOneService= scopedOneService;
    _scopedtwoService= scopedtwoService;
}

对于这个构造函数,我将像这样注入这些实例:

_app.UseMiddleware<WebSocketManagerMiddleware>(
    app.ApplicationServices.GetWebSocketConnectionDictionary(),
    serviceProvider.CreateScope().ServiceProvider.GetScopedOneService(),
    serviceProvider.CreateScope().ServiceProvider.GetScopedTwoService())

恐怕我每次在 WebSocket 请求上都会从我获得作用域服务(serviceOne、serviceTwo)的地方创建新的作用域,并且在 WebSocket 连接关闭之前它永远不会被释放。因为我只在 websocket 启动时使用这些服务,并且在我开始收听即将到来的消息后我从不使用它们(IScopedOneSerice,IScopedTwoService)

public async Task Invoke(HttpContext context, IServiceProvider service)
{
    await _scopedOneService.MethodOne();
    await _scopedTwoService.MethodTwo();
    //startint to listen for messages and if I need to call some repository 
    // method I am using 
    //IServiceProvider, i.e ISomeRepository repo =
    //    service.GetRequiredService<ISomeRepository>(); // this repo scoped as well
}

这种方式是否可能导致内存泄漏?

更新: 我想要实现的目标:让我们简单点,每次我收到 websocket 消息时,我都需要将消息插入存储库或解析与其他业务逻辑服务通信的其他一些服务。

我不确定将作用域服务注入包含单例 websocket 字典和一些其他作用域服务的 websocket 中间件的最佳方法是什么。

正如我在评论中所说,您应该注入 IServiceScopeFactory 而不是作用域服务。然后您可以使用它来解析作用域服务。

public WebSocketManagerMiddleware(RequestDelegate next,
    IWebSocketConnectionDictionary webSocketDictionary,
    IServiceScopeFactory scopeFactory)
{
    _next = next;
    _webSocketManager = webSocketDictionary;
    _scopeFactory = scopeFactory;
}

然后您可以创建一个新范围并在需要访问它们时从那里解析服务。

using (var scope = _scopeFactory.CreateScope())
{
    var scopedOneService = scope.ServiceProvider.GetRequiredService<IScopedServiceOne>();
    var scopedTwoService = scope.ServiceProvider.GetRequiredService<IScopedServiceTwo>();
    // do something with scoped services
}

您还应该阅读 ,它在这种情况下是正确的,但在克里斯的回答所针对的问题的情况下却不是,这就是它被否决的原因:)