SignalR: Give IHubContext more flexibility to deal with generics
See original GitHub issueSummary
Right now, it is only possible to inject generic-type IHubContext objects. Since Clients and Groups do not require the generic type we can abstract the IHubContext even further so that IHubContext<> and IHubContext<,> implement IHubContext (with no generic type).
Motivation and goals
This change gives the flexibility needed to perform generic casting from some IHubContext<SomeHub> to IHubContext while being able to use the Clients and/or Groups properties. Can this be considered for a later major update?
In scope
You may have a unique notification service dispatching messages to some clients based on the specific hub type + connection id.
Out of scope
N/A.
Risks / unknowns
None that I can think of.
Examples
We need some codebase:
[HubName(EventStreamNames.Dashboard)]
public class MyHub : Hub { }
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class HubNameAttribute : Attribute
{
public string HubName { get; set; }
public HubNameAttribute(string hubName)
{
HubName = hubName;
}
}
public interface IHubContextResolver
{
IHubContext GetHubContext(string hubName);
}
internal class HubContextResolver : IHubContextResolver
{
private readonly IServiceProvider serviceProvider;
public HubContextResolver(IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider;
}
public IHubContext GetHubContext(string hubName)
{
var hubType = AppDomain.CurrentDomain
.GetAssemblies()
.SelectMany(a => a.GetTypes())
.Where(t => t.IsAssignableTo(typeof(Hub)))
.FirstOrDefault(t => t.GetCustomAttribute<HubNameAttribute>(true)?.HubName == hubName);
var hubContextType = typeof(IHubContext<>).MakeGenericType(hubType);
return serviceProvider.GetService(hubContextType) as IHubContext;
}
}
Then, it can be used by a general-purpose handler.
public class NotificationHandler : MessageHandler<SignalRNotification>
{
private readonly IHubContextResolver _hubContextResolver;
public NotificationHandledHandler(IHubContextResolver hubContextResolver)
{
_hubContextResolver = hubContextResolver;
}
public override async Task Handle(SignalRNotification request, CancellationToken cancellationToken)
{
var hub = _hubContextResolver.GetHubContext(request.Hub);
if (hub != null)
{
await hub.Clients.Client(request.ConnectionId).SendCoreAsync(request.Method, new[] { request.Data });
}
}
}
Issue Analytics
- State:
- Created 3 years ago
- Reactions:1
- Comments:9 (7 by maintainers)
Top Results From Across the Web
SignalR HubContext
Learn how to use the ASP.NET Core SignalR HubContext service for sending notifications to clients from outside a hub.
Read more >Mocking ApiController SignalR broadcasting
Base ApiController tightly coupled to static accessor of the hub context. This needs to be refactored out into its own service to allow...
Read more >Simplifying Real-Time Communication with SignalR
Discover the potential of SignalR, a powerful real-time communication library, in our comprehensive introduction with practical examples.
Read more >Real-time Angular 11 Application With SignalR And .NET 5
In this post, we will see how to create a real-time SignalR application with ... We can add one more DbSet property for...
Read more >Self-Hosting SignalR in a Windows Service - Rick Strahl
In this post I show an example of a Windows Service that integrates SignalR to provide real time status updates and describe the...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Turning this into a more formal API proposal:
I’m not sure if this is a breaking API change.
When we do this, we should also make
IHubClients<T>
covariant.