0Pricing
C# Academy · บทเรียน

ฮับแบบระบุชนิดอย่างเคร่งครัด

กำหนดอินเทอร์เฟซฮับที่ระบุชนิด เพื่อความปลอดภัยขณะคอมไพล์และรองรับ IntelliSense สำหรับการเรียกเมธอดของไคลเอ็นต์

ฮับแบบระบุชนิดอย่างเคร่งครัด เป็นบทเรียน C# Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน 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>

การส่งข้อมูลแบบมีโครงสร้าง

เมธอดในอินเทอร์เฟซฝั่งไคลเอนต์สามารถรับอ็อบเจ็กต์ถ่ายโอนข้อมูลที่ซับซ้อนได้ SignalR จะแปลงอ็อบเจ็กต์เหล่านั้นเป็นเจสันโดยอัตโนมัติ — ตรวจสอบให้แน่ใจว่าชนิดข้อมูลของคุณสามารถแปลงเป็นรูปแบบดังกล่าวได้

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 ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส C# Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส C# Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “ฮับแบบระบุชนิดอย่างเคร่งครัด”

กำหนดอินเทอร์เฟซฮับที่ระบุชนิด เพื่อความปลอดภัยขณะคอมไพล์และรองรับ IntelliSense สำหรับการเรียกเมธอดของไคลเอ็นต์ คุณปฏิบัติ C# Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน C# Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน C# Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน

บทเรียน “ฮับแบบระบุชนิดอย่างเคร่งครัด” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน C# Academy นี้ได้ไหม

ได้ บทเรียน C# Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. ฮับและการเชื่อมต่อ SignalR
  2. กลุ่ม ผู้ใช้ และการจัดการการเชื่อมต่อ
  3. ฮับแบบระบุชนิดอย่างเคร่งครัด
  4. การปรับขนาดด้วย Redis Backplane
← กลับไปที่ C# Academy