-
Notifications
You must be signed in to change notification settings - Fork 10.4k
Closed
Labels
api-approvedAPI was approved in API review, it can be implementedAPI was approved in API review, it can be implementedarea-signalrIncludes: SignalR clients and serversIncludes: SignalR clients and serversdesign-proposalThis issue represents a design proposal for a different issue, linked in the descriptionThis issue represents a design proposal for a different issue, linked in the description
Milestone
Description
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 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 });
}
}
}
douglasg14b
Metadata
Metadata
Assignees
Labels
api-approvedAPI was approved in API review, it can be implementedAPI was approved in API review, it can be implementedarea-signalrIncludes: SignalR clients and serversIncludes: SignalR clients and serversdesign-proposalThis issue represents a design proposal for a different issue, linked in the descriptionThis issue represents a design proposal for a different issue, linked in the description