C# Academy · Lekcja

Silnie typowane huby

Definiuj typowane interfejsy hubów, aby uzyskać bezpieczeństwo na etapie kompilacji i IntelliSense dla wywołań metod klienta.

Lekcja 3 z 412 kroki

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 nie Task<T>
  • Klientów opartych na interfejsie można mockować — silnie typowane huby są łatwiejsze do testowania
Bezpłatny start

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

  1. Huby i połączenia SignalR
  2. Grupy, użytkownicy i zarządzanie połączeniami
  3. Silnie typowane huby
  4. Skalowanie z Redis Backplane
← Powrót do C# Academy