其实微软在.NET Framework时代就有Redis和Signalr的解决方案了。只不过我没有花心思去找源码。.NET Core版本的源码倒是很全。我们在用signalR的时候。是会先创建一个ChatHub继承Hub
public class ChatHub:Hub { public async Task SendMessage(string user,string message) { await Clients.All.SendAsync("ReceiveMessage", user, message); } }
可以看到这里是调用了Clients.All.SendAsync方法。我们查看源码,可以看到Hub是一个抽象类
public abstract class Hub : IDisposable { private bool _disposed; private IHubCallerClients _clients; private HubCallerContext _context; private IGroupManager _groups; /// <summary> /// Gets or sets an object that can be used to invoke methods on the clients connected to this hub. /// </summary> public IHubCallerClients Clients { get { CheckDisposed(); return _clients; } set { CheckDisposed(); _clients = value; } } }
在Hub中的Clients继承IHubCallerClients的。我们通过Crtl+F12查看实现找到HubCallerClients。所以不难看出上文中的Clients其实是HubCallerClients对象。在HubCallerClients中可以找到这段代码
public IClientProxy All => _hubClients.All;
而这个_hubClients其实是HubClients。在HubClients的构造函数中我们可以看到
public HubClients(HubLifetimeManager<THub> lifetimeManager) { _lifetimeManager = lifetimeManager; All = new AllClientProxy<THub>(_lifetimeManager); }
HubLifetimeManager是一个抽象类。在这里我们用Redis做底板的时候。在这段代码里就完成了
HubLifetimeManager的注册
public static ISignalRServerBuilder AddStackExchangeRedis(this ISignalRServerBuilder signalrBuilder, Action<RedisOptions> configure) { signalrBuilder.Services.Configure(configure); signalrBuilder.Services.AddSingleton(typeof(HubLifetimeManager<>), typeof(RedisHubLifetimeManager<>)); return signalrBuilder; }
而这个AllClientProxy对象其实很干净。只有一个方法
internal class AllClientProxy<THub> : IClientProxy where THub : Hub { private readonly HubLifetimeManager<THub> _lifetimeManager; public AllClientProxy(HubLifetimeManager<THub> lifetimeManager) { _lifetimeManager = lifetimeManager; } public Task SendCoreAsync(string method, object[] args, CancellationToken cancellationToken = default) { return _lifetimeManager.SendAllAsync(method, args); } }
所以上面的Clients.All其实是AllClientProxy对象。至于SendAsync其实是一个扩展方法
public static Task SendAsync(this IClientProxy clientProxy, string method, object arg1, object arg2, CancellationToken cancellationToken = default) { return clientProxy.SendCoreAsync(method, new[] { arg1, arg2 }, cancellationToken); }
可以看到,此时Clients.All.SendAsync实际上是调用AllClientProxy的SendCoreAsync方法