question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

SignalR: Give IHubContext more flexibility to deal with generics

See original GitHub issue

Summary

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:closed
  • Created 3 years ago
  • Reactions:1
  • Comments:9 (7 by maintainers)

github_iconTop GitHub Comments

1reaction
davidfowlcommented, Mar 22, 2021

Turning this into a more formal API proposal:

public interface IHubContext
{
   IHubClients Clients { get; }
   IGroupManager Groups { get; }
}

public interface IHubContext<THub> : IHubContext
{
}

// potentially also
public interface IHubContext<THub, T>
        where THub : Hub<T>
        where T : class
        : IHubContext
{
}

I’m not sure if this is a breaking API change.

0reactions
halter73commented, Mar 22, 2021

When we do this, we should also make IHubClients<T> covariant.

Read more comments on GitHub >

github_iconTop 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 >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found