簡體   English   中英

依賴注入到 SignalR 集線器(dotnet core 3.1)

[英]Dependency Injection into SignalR Hub (dotnet core 3.1)

我正在使用 SignalR 並且在讓 DI 進入 SignalR 集線器時遇到問題。 我以為它會使用現有的 dotnet core DI 框架,但似乎並非如此。 我不斷得到

System.InvalidOperationException: Unable to resolve service for type 'Comcast.Cs.Mercury.Web.Api.IHubClientHelper' while attempting to activate 'mercury_ms_auth.Hubs.AuthenticationHub'.
   at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetService(IServiceProvider sp, Type type, Type requiredBy, Boolean isDefaultParameterRequired)
   at lambda_method(Closure , IServiceProvider , Object[] )
   at Microsoft.AspNetCore.SignalR.Internal.DefaultHubActivator`1.Create()
   at Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher`1.OnConnectedAsync(HubConnectionContext connection)
   at Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher`1.OnConnectedAsync(HubConnectionContext connection)
   at Microsoft.AspNetCore.SignalR.HubConnectionHandler`1.RunHubAsync(HubConnectionContext connection)

我注冊了 singleton:

            services.AddSingleton<IHubClientHelper>(new HubClientHelper(loggerFactory.CreateLogger<HubClientHelper>())
            {
                ClientConnectionType = _environment.IsDevelopment()
                    ? ClientConnectionType.ConnectionId
                    : ClientConnectionType.UserId
            });

而且我有依賴進入集線器的構造函數:

public AuthenticationHub(TelemetryClient telemetryClient, IHubClientHelper clientHelper)
            : base(telemetryClient, clientHelper)
        {
            
        }

文檔表明這應該有效。 有任何想法嗎?

您的問題不是很清楚,但我將嘗試回答您如何正確注冊集線器並使用 DI 注入它。 首先,您在啟動時添加集線器:

services.AddSignalR(hubOptions =>
{
    hubOptions.ClientTimeoutInterval = TimeSpan.FromSeconds(hostConfiguration.SignalR.ClientTimeoutInterval);
    hubOptions.HandshakeTimeout = TimeSpan.FromSeconds(hostConfiguration.SignalR.HandshakeTimeout);
    hubOptions.KeepAliveInterval = TimeSpan.FromSeconds(hostConfiguration.SignalR.KeepAliveInterval);
    hubOptions.EnableDetailedErrors = hostConfiguration.SignalR.EnableDetailedErrors;
    hubOptions.MaximumReceiveMessageSize = hostConfiguration.SignalR.MaximumReceiveMessageSize;
    hubOptions.StreamBufferCapacity = hostConfiguration.SignalR.StreamBufferCapacity;
});
app.UseSignalR(routes =>
{
    routes.MapHub<YourHub>(/yourHub);
});

因此,這會將您的集線器添加為transient 然后你可以像這樣注入你的集線器:

private IHubContext<YourHub, IYourHub> YourHub
{
    get
    {
        return this.serviceProvider.GetRequiredService<IHubContext<YourHub, IYourHub>>();
    }
}

還有一些注意事項:

SignalR 期望為每條消息單獨創建集線器。 如果您希望集線器處於 DI 中,則需要將其添加為瞬態服務。 您通常不應該將集線器從 DI 中解析出來。 如果您需要在 Hub 和其他一些組件之間共享代碼,我建議使用 IHubContext 或將共享代碼放在單獨的 DI 服務中。

發現了問題。 我正在使用 Unity Container,結果發現該容器沒有像 OOTB DI 框架那樣自動注冊 ILogger。 我通過使用 Immediate Window 嘗試解決 IHubClientHelper 發現了這一點,它最終告訴我它無法解析 ILogger ( No public constructor is available for type Microsoft.Extensions.Logging.ILogger. )。 在快速谷歌之后,我找到了這個,並通過將以下內容添加到 Startup.cs 中的 ConfigureContainer 方法,我再次啟動並運行。

var logFactory = new LoggerFactory();
container.AddExtension(new LoggingExtension(logFactory));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM