强类型中心
定义类型化中心接口,为客户端方法调用获得编译时安全性和 IntelliSense 支持。
强类型中心 是 CoddyKit 上的免费 C# Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 C# Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 C# Academy 课程共包含 4 节课。
字符串方法名称的问题
标准 SignalR 调用使用 SendAsync("MethodName", ...),其中包含魔法字符串。方法名称中的拼写错误会导致静默失败——客户端根本不会收到消息。强类型中心可以解决这个问题。
定义客户端接口
创建一个接口,声明服务器可以在客户端调用的每个方法。方法名称和参数类型就是您的契约。
// INotificationClient.cs
public interface INotificationClient
{
Task ReceiveMessage(string user, string message);
Task OrderShipped(int orderId, string trackingNumber);
Task UserJoined(string username);
Task UserLeft(string username);
Task SystemAlert(string message);
}创建强类型中心
请继承自 Hub<T>,其中 T 是您的客户端接口。此时 Clients 属性具有类型信息——IntelliSense 会显示可用方法,而拼写错误会在编译时报告错误。
public class ChatHub : Hub<INotificationClient>
{
public async Task SendMessage(string message)
{
var user = Context.User!.Identity!.Name ?? "Anonymous";
// Compile-time safety — no magic strings!
await Clients.All.ReceiveMessage(user, message);
await Clients.Others.UserJoined(user); // IntelliSense works
}
}使用强类型中心定位特定客户端
所有标准的目标选择方法在强类型中心上都可用:Clients.User、Clients.Group、Clients.Caller、Clients.Client——并且都会返回强类型接口。
public async Task NotifyOrderShipped(int orderId, string customerId)
{
await Clients.User(customerId)
.OrderShipped(orderId, "TRK-12345");
await Clients.Group("admins")
.SystemAlert($"Order {orderId} shipped to {customerId}");
await Clients.Caller.ReceiveMessage("System", "Notification sent");
}强类型 IHubContext
将 IHubContext<THub, TClient> 注入服务中,即可在从中心外部推送消息时获得相同的编译时安全性。
public class ShipmentService
{
private readonly IHubContext<ChatHub, INotificationClient> _hub;
public ShipmentService(
IHubContext<ChatHub, INotificationClient> hub) => _hub = hub;
public async Task ProcessShipmentAsync(int orderId, string customerId)
{
// Fully typed — no magic strings
await _hub.Clients.User(customerId)
.OrderShipped(orderId, "TRK-99999");
}
}客户端接口规则
客户端接口中的方法必须返回 Task(而不是 Task<T>)。SignalR 会触发客户端调用但不等待结果——客户端不会向服务器返回值。
// CORRECT
public interface IMyClient
{
Task ReceiveMessage(string msg); // OK
Task UpdateProgress(int percent); // OK
Task<string> GetUserInput(); // NOT SUPPORTED
}
// Return types other than Task are not supported in hub client interfaces
// For request-response patterns, use client-callable hub methods instead将强类型中心与组结合使用
强类型组的工作方式与非强类型组完全相同——API 相同,只是方法名称在编译时受到检查。
public class RoomHub : Hub<IRoomClient>
{
public async Task JoinRoom(string room)
{
await Groups.AddToGroupAsync(Context.ConnectionId, room);
await Clients.Group(room).UserJoined(Context.User!.Identity!.Name!);
}
public async Task BroadcastToRoom(string room, string message)
{
var user = Context.User!.Identity!.Name!;
await Clients.Group(room).ReceiveMessage(user, message);
}
}测试强类型中心
由于客户端方法调用通过接口进行,因此您可以在单元测试中模拟客户端,以验证调用了正确的方法并传入了正确的参数。
// NSubstitute test
var mockClients = Substitute.For<IHubCallerClients<INotificationClient>>();
var mockAllClients = Substitute.For<INotificationClient>();
mockClients.All.Returns(mockAllClients);
var hub = new ChatHub { Clients = mockClients };
await hub.SendMessage("Hello!");
await mockAllClients.Received(1).ReceiveMessage("System", "Hello!");每个应用程序使用多个中心
一个应用程序可以为不同的实时功能设置多个中心终结点,每个终结点都有自己的强类型客户端接口。
// Three separate hubs
app.MapHub<ChatHub>("/hubs/chat");
app.MapHub<NotificationHub>("/hubs/notifications");
app.MapHub<DashboardHub>("/hubs/dashboard");
// Each with its own client interface:
// Hub<IChatClient>, Hub<INotificationClient>, Hub<IDashboardClient>发送结构化数据
客户端接口方法可以接受复杂的 DTO。SignalR 会自动将它们序列化为 JSON——请确保您的类型可序列化。
public interface IOrderClient
{
Task OrderUpdated(OrderStatusDto status);
}
public record OrderStatusDto(
int OrderId,
string Status,
decimal Total,
DateTime UpdatedAt);
// Usage in hub:
await Clients.User(customerId).OrderUpdated(
new OrderStatusDto(order.Id, order.Status.ToString(),
order.Total, DateTime.UtcNow));快速检查
SignalR 中心客户端接口中的方法,其返回类型有什么限制?
回顾:强类型中心
要点:
- 定义接口(IMyClient),列出服务器可以在客户端调用的所有方法
- 继承自
Hub<IMyClient>——Clients 属性将成为完整的强类型属性 - 注入
IHubContext<THub, TClient>,以便从中心外部进行强类型推送 - 客户端接口方法必须返回
Task,而不是Task<T> - 基于接口的客户端可以进行模拟——强类型中心更易于测试
常见问题解答
「强类型中心」课时是免费的吗?
是的 — 「强类型中心」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 C# Academy 课程的其余内容,请升级到 CoddyKit PRO。 C# Academy 课程共包含 4 节课。
「强类型中心」这节课中我会学到什么?
定义类型化中心接口,为客户端方法调用获得编译时安全性和 IntelliSense 支持。 你通过在浏览器中直接运行的动手代码来练习 C# Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 C# Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 C# Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「强类型中心」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 C# Academy 课中编写并运行代码吗?
能。每节 C# Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。