0Pricing
C# Academy · درس

المراكز محدّدة الأنواع

عرّفوا واجهات مراكز محدّدة الأنواع للحصول على أمان وقت الترجمة وIntelliSense عند استدعاء أساليب العميل.

المراكز محدّدة الأنواع درس مجاني في C# Academy على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 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 العميل بطريقة fire-and-forget — ولا توجد قيمة إرجاع من العميل إلى الخادم.

// 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

دمج المراكز ذات الأنواع مع المجموعات

تعمل المجموعات ذات الأنواع بالطريقة نفسها تمامًا مثل المجموعات غير ذات الأنواع — فواجهة برمجة التطبيقات نفسها، لكن مع أسماء أساليب محددة في وقت الترجمة.

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>

إرسال البيانات المهيكلة

يمكن لأساليب واجهة العميل قبول DTOs معقدة. ويحوّلها 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>
  • يمكن إنشاء محاكاة للعملاء القائمين على الواجهة — لذا يسهل اختبار المراكز ذات الأنواع القوية

الأسئلة الشائعة

هل درس «المراكز محدّدة الأنواع» مجاني؟

نعم — نص درس «المراكز محدّدة الأنواع» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة C# Academy، انتقل إلى CoddyKit PRO. تتضمن دورة C# Academy 4 دروس في المجموع.

ماذا ستتعلم في «المراكز محدّدة الأنواع»؟

عرّفوا واجهات مراكز محدّدة الأنواع للحصول على أمان وقت الترجمة وIntelliSense عند استدعاء أساليب العميل. تتمرن على C# Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ C# Academy؟

لا تُشترط خبرة سابقة. C# Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.

كم من الوقت يستغرق درس «المراكز محدّدة الأنواع»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس C# Academy هذا؟

نعم. كل درس في C# Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. مراكز SignalR والاتصالات
  2. المجموعات والمستخدمون وإدارة الاتصالات
  3. المراكز محدّدة الأنواع
  4. التوسّع باستخدام Redis Backplane
← العودة إلى C# Academy