ฮับแบบระบุชนิดอย่างเคร่งครัด
กำหนดอินเทอร์เฟซฮับที่ระบุชนิด เพื่อความปลอดภัยขณะคอมไพล์และรองรับ 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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- ฮับและการเชื่อมต่อ SignalR
- กลุ่ม ผู้ใช้ และการจัดการการเชื่อมต่อ
- ฮับแบบระบุชนิดอย่างเคร่งครัด
- การปรับขนาดด้วย Redis Backplane