使用范围服务的Websocket单例

时间:2019-10-14 12:11:25

标签: c# dependency-injection websocket .net-core middleware

我已经实现了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中间件中的最佳方法是什么。

1 个答案:

答案 0 :(得分:1)

如我的评论中所述,您应该注入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
}

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