Get Hub Context in SignalR Core from within another object

前端 未结 2 1292
悲&欢浪女
悲&欢浪女 2020-12-10 05:13

I am using Microsoft.AspNetCore.SignalR (latest release) and would like to get the hub context from within another object that\'s not a Controller.

相关标签:
2条回答
  • 2020-12-10 05:49

    So after looking over this example from the accepted answer, I didn't quite get where he was going, so I tried a few things and I think I got what he was saying. So, for folks who have this issue in the future, I want to change that example to a fully working example.

    So we are going to create a "Shared Methods", like in the example:

    using Microsoft.AspNetCore.SignalR;
    using System.Threading.Tasks;
    
    namespace YouDontNeedToKnow.Core.Main.Hubs
    {
        internal class HubMethods<THub> where THub : Hub
        {
            private readonly IHubContext<THub> _hubContext;
    
            public HubMethods(IHubContext<THub> hubContext)
            {
                _hubContext = hubContext;
            }
    
            public Task InvokeOnGroupAsync(string groupName, string method, params object[] args) =>
                _hubContext.Clients.Group(groupName).InvokeAsync(method, args);
    
            public Task InvokeOnAllAsync(string method, params object[] args) =>
                _hubContext.Clients.All.InvokeAsync(method, args);
    
            public Task AddConnectionIdToGroupAsync(string connectionId, string groupName) =>
                _hubContext.Groups.AddAsync(connectionId, groupName);
    
            // ...
        }
    }
    

    Then, in your Hub object, you add a constructor, like so:

    using System;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.SignalR;
    
    namespace YouDontNeedToKnow.Core.Main.Hubs
    {
        internal class MyHub : Hub
        {
            public static string HubName => "myHub";
    
            private readonly HubMethods<MyHub> _hubMethods;
    
            public PlayerServicesHub(HubMethods<MyHub> hubMethods)
            {
                _hubMethods = hubMethods;
            }
    
            public override Task OnConnectedAsync()
            {
                return base.OnConnectedAsync();
            }
        }
    }
    

    In your Startup.cs, you inject the shared class like so:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddTransient<HubMethods<MyHub>>();
        services.AddSignalR();
        services.AddMvc();
    }
    

    This still works as it normally would:

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IServiceProvider sp)
    {
        app.UseDefaultFiles();
        app.UseStaticFiles();
        app.UseSignalR(routes =>
        {
            routes.MapHub<MyHub>(MyHub.HubName);
        });
        app.UseMvc();
        // This is just an example line of how you can get the hub with context:
        var myHub = sp.GetService<HubMethods<MyHub>>();
    }
    
    0 讨论(0)
  • 2020-12-10 05:53

    Just set IHubContext<MyHub> hubContext on calling-side constructor.

    I would recommend using .net core default DI container mechanism, not creating static property.

    Please refer to How do I get a reference to a Hub?

    public class MyHub : Hub
    {
    }
    
    public class CallingSideClass
    {
        private readonly IHubContext<MyHub> _hubContext;
    
        public CallingSideClass(IHubContext<MyHub> hubContext)
        {
            _hubContext = hubContext;
        }
    
        public async Task FooMethod(...)
        {
            await _hubContext.Clients.All.InvokeAsync(...);
        }
    }
    
    public class Startup
    {...
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddSignalR();
            services.AddScoped<CallingSideClass>();
        }
        ... 
    }
    
    0 讨论(0)
提交回复
热议问题