البرمجة وتطوير البرمجيات

كيفية استخدام unions والتسلسلات المغلقة في ASP.NET Core

يوضح .NET Blog كيفية توظيف أنواع unions والتسلسلات الهرمية المغلقة مع System.Text.Json عبر Minimal APIs وMVC وSignalR وBlazor وOpenAPI. كما يحدد حالات الالتباس ومصادر الربط التي لا تدعم هذه الأنواع.

10 سبتمبر 2026
4 دقائق قراءة
1 قراءة
فريق تحرير certi.news
كيفية استخدام unions والتسلسلات المغلقة في ASP.NET Core

يقدم ASP.NET Core في .NET 11 دعماً عملياً لاستخدام أنواع union والتسلسلات الهرمية المغلقة مع System.Text.Json، بما يسمح بتمثيل قيمة يمكن أن تنتمي إلى أكثر من نوع أو عائلة محددة من الأنواع. ويمتد هذا الدعم إلى Minimal APIs ووحدات تحكم MVC وSignalR وBlazor ووثائق OpenAPI، مع اختلافات مهمة في طريقة القراءة والكتابة وحدود ربط المعلمات.

متى يكون union مناسباً؟

يناسب union العقود التي تقبل بدائل مستقلة من دون الحاجة إلى غلاف JSON أو حقل discriminator. ومن أمثلة ذلك قيمة يمكن أن تكون رقماً صحيحاً أو سلسلة نصية، أو إعداداً يقبل قيمة منطقية أو كائناً يضم خيارات أكثر تفصيلاً. عند التسلسل، تُكتب الحالة النشطة مباشرة بصيغتها الطبيعية؛ فلا يضاف غلاف خاص بنوع union ولا discriminator.

تُسلسل الحالات التي يمكن تمييزها بوضوح من بنية JSON تلقائياً. لكن إذا تشاركت الحالات البنية نفسها، مثل union يضم كائنَي Cat وDog، فلن يستطيع System.Text.Json تحديد النوع من رمز JSON وحده. في هذه الحالة يمكن توفير JsonTypeClassifier مخصص لاختيار الحالة الصحيحة. وينطبق الأمر ذاته على بعض عقود الطلبات التي تقبل رقماً أو سلسلة، إذ تسمح إعدادات JSON الخاصة بالويب بقراءة الأرقام من السلاسل، ما قد يجعل النص قابلاً للتفسير بوصفه أيّاً من الحالتين.

التسلسلات الهرمية المغلقة تختلف عن union

لا يعني استخدام المعدّل closed أن التسلسل متعدد الأشكال سيُفعّل تلقائياً. فعند التعامل مع نوع مشتق ملموس مثل PaymentAuthorized، يتعامل System.Text.Json معه كأي نوع آخر، ويُنتج JSON يتضمن paymentId وamount من دون discriminator.

أما عند استخدام النوع الأساسي PaymentEvent في واجهة API، فيلزم تحديد النوع المشتق الذي يجب إنشاؤه. ويمكن تفعيل ذلك على النوع الأساسي باستخدام JsonPolymorphic(InferClosedTypePolymorphism = true)، أو عبر JsonSerializerOptions.InferClosedTypePolymorphism. عندها يستنتج System.Text.Json الأنواع المشتقة في التسلسل المغلق ويستخدم أسماءها كمعرّفات، مثل $type بقيمة PaymentAuthorized.

الاختيار بين النموذجين يعتمد على طبيعة العقد: يمثل union بدائل قد لا تنتمي إلى عائلة واحدة، بينما تلائم التسلسلات المغلقة مجموعة مترابطة من الأحداث أو الكيانات تحتاج إلى discriminator واضح.

الدعم عبر طبقات ASP.NET Core

في Minimal APIs، يمكن استخدام union كمعلمة لجسم الطلب أو كنوع للإرجاع، سواء في المسار التنفيذي المعتاد أو عبر Request Delegate Generator، مع سلوك متماثل بين المسارين. كما يمكن أن يظهر union داخل نموذج آخر، أو كعنصر في IAsyncEnumerable، أو ضمن حاوية تستخدم AsParameters، وتظل إعدادات ConfigureHttpJsonOptions مؤثرة في التسلسل.

وتدعم وحدات تحكم MVC unions كمعلمات للإجراءات وأنواع للإرجاع، بما في ذلك Task<TUnion> وValueTask<TUnion>. وبما أن MVC يستخدم إعدادات JsonSerializerDefaults.Web، فإن مشكلة الالتباس بين الرقم والسلسلة في مدخلات HTTP تنطبق عليه أيضاً.

في SignalR، يعمل الدعم عبر JsonHubProtocol للمعلمات وقيم الإرجاع وعناصر التدفق. ولا يحتاج union من نوع int أو string إلى classifier عند استخدام هذا البروتوكول، لأن JsonHubProtocol لا يعامل رمز JSON النصي بوصفه ملتبساً في هذه الحالة. لكن unions التي تتشارك الحالات فيها رمز StartObject، مثل UnionPet(Cat, Dog)، تظل بحاجة إلى classifier. ولا يدعم SignalR هذه الوظيفة عند استخدام MessagePack أو Newtonsoft.Json hub protocols.

Blazor وOpenAPI

تعمل معلمات مكونات Blazor داخل العملية عبر إسناد مباشر، ولذلك لا تحتاج إلى تسلسل. لكن JavaScript interop وحالة المكونات المحفوظة والمعلمات أثناء prerendering تمر عبر System.Text.Json، فتتبع قواعد unions نفسها. ويمكن مثلاً تمرير union إلى JavaScript بصيغة Boolean أو كائن خيارات، وفق الحالة النشطة، من دون إضافة غلاف أو discriminator.

في OpenAPI، يُمثّل union باستخدام مخطط anyOf يضم نوعاً لكل حالة. وتعيد الحالات استخدام أسماء مكونات Cat وDog نفسها عند ظهورها كأنواع مستقلة. ويختلف ذلك عن الأنواع متعددة الأشكال التي تحمل discriminator وتُرفع مخططاتها بأسماء مميزة. كما يمكن لـ ApiExplorer تمثيل عدة أنواع استجابة لنفس رمز الحالة ونوع المحتوى ضمن anyOf.

القيود التي يجب مراعاتها

يعتمد دعم unions على System.Text.Json، ولذلك لا يعمل مع مصادر الربط التي لا تمر عبر تحليل JSON. وتشمل هذه المصادر قيم query string وقيم المسارات والرؤوس وحقول النماذج. فقيمة مثل ?id=42 لا تكفي لتحديد ما إذا كان المقصود int أو string أو Guid. وينطبق القيد في Blazor على [SupplyParameterFromQuery] والربط من النماذج باستخدام [SupplyParameterFromForm]. ويشير المصدر إلى أن ربط union من هذه المصادر ما زال موضع دراسة وجمع ملاحظات.

القراءة التحريرية: القيمة الأساسية هنا ليست إضافة صيغة جديدة للـJSON، بل توحيد التعامل مع عقود متعددة الحالات عبر أجزاء واسعة من منظومة .NET 11. غير أن نجاح التصميم يتوقف على قابلية الحالات للتمييز وعلى مصدر البيانات؛ لذلك ينبغي تحديد classifier أو discriminator مبكراً، وعدم افتراض أن دعم التسلسل يعني دعم كل طرق ربط المعلمات.

مصدر الخبر
كيف أعددنا هذا الخبر؟

اعتمد الخبر على المصدر الأصلي الموضح أعلاه. قد نستخدم أدوات آلية للمساعدة في الاستخراج والتصنيف والصياغة، لكن النشر يخضع لقواعد تمنع المحتوى المكرر والقصير أو الروتيني منخفض القيمة. اقرأ سياستنا التحريرية.

ف
كاتب المقال

فريق تحرير certi.news

فريق التحرير

فريق تحرير certi.news يتابع المصادر التقنية ويعيد بناء الأخبار بالعربية مع مراجعة الحقائق والسياق قبل النشر.

من نفس التصنيف

مقالات قد تهمك

عرض جميع المقالات