简体   繁体   English

依赖注入到 SignalR 集线器(dotnet core 3.1)

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

I'm using SignalR and having an issue getting DI to work into a SignalR hub.我正在使用 SignalR 并且在让 DI 进入 SignalR 集线器时遇到问题。 I assumed it would use the existing dotnet core DI framework, but that doesn't seem to be the case.我以为它会使用现有的 dotnet core DI 框架,但似乎并非如此。 I keep getting我不断得到

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)

I registered the singleton:我注册了 singleton:

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

And I have the dependency coming into the constructor of the hub:而且我有依赖进入集线器的构造函数:

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

Documentation indicates this should work.文档表明这应该有效。 Any ideas?有任何想法吗?

Your question is not very clear, but I will try to answer how you correctly register your hub and inject it using DI.您的问题不是很清楚,但我将尝试回答您如何正确注册集线器并使用 DI 注入它。 First of all you add your hub on startup:首先,您在启动时添加集线器:

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);
});

So this will add your hub as a transient .因此,这会将您的集线器添加为transient Then you can inject your hub like:然后你可以像这样注入你的集线器:

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

And some notes:还有一些注意事项:

SignalR expects the Hub to be created separately for each message. SignalR 期望为每条消息单独创建集线器。 You need to add it as a Transient service if you want your Hub to be in DI.如果您希望集线器处于 DI 中,则需要将其添加为瞬态服务。 You generally shouldn't resolve the Hub out of DI.您通常不应该将集线器从 DI 中解析出来。 If you need to share code between your Hub and some other component, I'd suggest using either IHubContext or putting the shared code in a separate DI service instead.如果您需要在 Hub 和其他一些组件之间共享代码,我建议使用 IHubContext 或将共享代码放在单独的 DI 服务中。

Found the problem.发现了问题。 I'm using Unity Container and turns out the container doesn't get ILogger auto-registered like the OOTB DI framework does.我正在使用 Unity Container,结果发现该容器没有像 OOTB DI 框架那样自动注册 ILogger。 I found that out by using Immediate Window to try to Resolve IHubClientHelper and it finally told me that it couldn't resolve ILogger ( No public constructor is available for type Microsoft.Extensions.Logging.ILogger. ).我通过使用 Immediate Window 尝试解决 IHubClientHelper 发现了这一点,它最终告诉我它无法解析 ILogger ( No public constructor is available for type Microsoft.Extensions.Logging.ILogger. )。 After a quick google on that, I found this , and by adding the following to my ConfigureContainer method in Startup.cs, I was up and running again.在快速谷歌之后,我找到了这个,并通过将以下内容添加到 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