Silnie typowane huby
Definiuj typowane interfejsy hubów, aby uzyskać bezpieczeństwo na etapie kompilacji i IntelliSense dla wywołań metod klienta.
Silnie typowane huby to bezpłatna lekcja C# Academy na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej C# Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs C# Academy zawiera 4 lekcji w sumie.
Problem z nazwami metod jako ciągami znaków
Standardowe wywołania SignalR używają SendAsync("MethodName", ...) i magicznych ciągów znaków. Literówka w nazwie metody powoduje ciche niepowodzenie — klient po prostu nigdy nie otrzymuje wiadomości. Rozwiązaniem są silnie typowane huby.
Definiowanie interfejsu klienta
Należy utworzyć interfejs deklarujący każdą metodę, którą serwer może wywołać na kliencie. Nazwy metod i typy parametrów stanowią kontrakt.
// 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);
}Tworzenie silnie typowanego huba
Należy dziedziczyć po Hub<T>, gdzie T jest interfejsem klienta. Właściwość Clients jest teraz typowana — IntelliSense pokazuje dostępne metody, a literówki są wykrywane podczas kompilacji.
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
}
}Kierowanie wiadomości do konkretnych klientów za pomocą typowanego huba
W typowanym hubie działają wszystkie standardowe metody kierowania wiadomości: Clients.User, Clients.Group, Clients.Caller, Clients.Client — wszystkie zwracają typowany interfejs.
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");
}Typowany IHubContext
Należy wstrzyknąć IHubContext<THub, TClient> do usług, aby uzyskać takie samo bezpieczeństwo typów podczas kompilacji przy wysyłaniu wiadomości spoza huba.
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");
}
}Zasady dotyczące interfejsu klienta
Metody w interfejsie klienta muszą zwracać Task, a nie Task<T>. SignalR wywołuje metody klienta bez oczekiwania na wynik — klient nie zwraca serwerowi żadnej wartości.
// 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Łączenie typowanych hubów z grupami
Typowane grupy działają tak samo jak nietypowane — API jest identyczne, a różnica polega jedynie na sprawdzaniu nazw metod podczas kompilacji.
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);
}
}Testowanie silnie typowanych hubów
Ponieważ wywołania metod klienta odbywają się za pośrednictwem interfejsu, w testach jednostkowych można użyć obiektu mock klienta, aby sprawdzić, czy wywołano właściwe metody z odpowiednimi argumentami.
// 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!");Wiele hubów w jednej aplikacji
Aplikacja może udostępniać wiele punktów końcowych hubów przeznaczonych dla różnych funkcji czasu rzeczywistego, z których każdy ma własny typowany interfejs klienta.
// 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>Wysyłanie danych strukturalnych
Metody interfejsu klienta mogą przyjmować złożone obiekty DTO. SignalR automatycznie serializuje je do formatu JSON — należy upewnić się, że używane typy można serializować.
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));Szybkie sprawdzenie
Jakie ograniczenie dotyczące typu zwracanego obowiązuje dla metod w interfejsie klienta huba SignalR?
Podsumowanie: silnie typowane huby
Najważniejsze informacje:
- Należy zdefiniować interfejs (IMyClient) zawierający listę wszystkich metod, które serwer może wywołać na klientach
- Należy dziedziczyć po
Hub<IMyClient>— właściwość Clients staje się w pełni typowana - Należy wstrzyknąć
IHubContext<THub, TClient>, aby wysyłać typowane komunikaty spoza huba - Metody interfejsu klienta muszą zwracać
Task, a nieTask<T> - Klientów opartych na interfejsie można mockować — silnie typowane huby są łatwiejsze do testowania
Ucz się C# dzięki korepetycjom AI — za darmo
Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.
- Kursy
- 93
- Lekcje
- 346
Często zadawane pytania
Czy lekcja „Silnie typowane huby” jest bezpłatna?
Tak — pełny tekst „Silnie typowane huby” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu C# Academy, przejdź na CoddyKit PRO. Kurs C# Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Silnie typowane huby”?
Definiuj typowane interfejsy hubów, aby uzyskać bezpieczeństwo na etapie kompilacji i IntelliSense dla wywołań metod klienta. Ćwiczysz C# Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć C# Academy?
Nie wymagamy żadnego doświadczenia. C# Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.
Ile czasu zajmuje lekcja „Silnie typowane huby”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji C# Academy?
Tak. Każda lekcja C# Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Huby i połączenia SignalR
- Grupy, użytkownicy i zarządzanie połączeniami
- Silnie typowane huby
- Skalowanie z Redis Backplane