其實微軟在.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方法
