دليل: تحديث واجهات مع الأعضاء الافتراضي في C # 8.0

بدءًا من الإصدار C # 8.0 على .NET Core 3.0 ، عند إنشاء عضو في الواجهة ، يمكنك تحديد تنفيذه. السيناريو الأكثر شيوعًا هو إضافة أعضاء بشكل آمن إلى واجهة تم إصدارها بالفعل واستخدامها من قبل عدد لا يحصى من العملاء.

في هذا الدليل سوف تتعلم كيفية:


  • من الآمن تمديد الواجهات عن طريق إضافة طرق مع التطبيقات.
  • إنشاء تطبيقات ذات معلمات لمزيد من المرونة.
  • الحصول على الحق في تنفيذ تطبيقات أكثر تحديدا مع إمكانية التحكم اليدوي.



من أين تبدأ؟


تحتاج أولاً إلى تهيئة الجهاز للعمل مع .NET Core ، بما في ذلك برنامج التحويل البرمجي من معاينة C # 8.0. يتوفر برنامج التحويل البرمجي هذا بدءًا من Visual Studio 2019 ، أو باستخدام معاينة .NET Core 3.0 الأحدث لـ SDK . يتوفر أعضاء الواجهة الافتراضية بدءًا من .NET Core 3.0 (معاينة 4).


نظرة عامة على السيناريو


يبدأ هذا البرنامج التعليمي بالإصدار الأول من مكتبة علاقات العملاء. يمكنك الحصول على تطبيق المبتدئين في مستودعنا على جيثب . افترضت الشركة التي أنشأت هذه المكتبة أن العملاء الذين لديهم تطبيقات حالية سيقومون بتكييفها مع هذه المكتبة. تم تقديم تعريفات الحد الأدنى من الواجهة للتطبيق للمستخدمين:


public interface ICustomer { IEnumerable<IOrder> PreviousOrders { get; } DateTime DateJoined { get; } DateTime? LastOrder { get; } string Name { get; } IDictionary<DateTime, string> Reminders { get; } } 

تم تعريف الواجهة الثانية أيضًا والتي تعرض الترتيب:


 public interface IOrder { DateTime Purchased { get; } decimal Cost { get; } } 

بناءً على هذه الواجهات ، يمكن للفريق بناء مكتبة لمستخدميه لإنشاء أفضل تجربة للعملاء. كان هدف الفريق هو زيادة مستوى التفاعل مع العملاء الحاليين وتطوير العلاقات مع العملاء الجدد.


حان الوقت لتحديث المكتبة للإصدار التالي. واحدة من أكثر الميزات شعبية هي إضافة خصومات للعملاء المخلصين الذين يقدمون عددًا كبيرًا من الطلبات. يتم تطبيق هذا الخصم الفردي الجديد في كل مرة يقدم فيها العميل طلبًا ، مع كل تطبيق لـ ICustomer ، يمكن تعيين قواعد مختلفة للحصول على خصم للولاء.

الطريقة الأكثر ملاءمة لإضافة هذه الميزة هي توسيع واجهة ICustomer مع أي خصومات. هذا الاقتراح تسبب في قلق بين المطورين ذوي الخبرة. "واجهات غير قابلة للتغيير بعد الإفراج! هذا تغيير مهم! " في C # 8.0 ، تمت إضافة تطبيقات الواجهة الافتراضية لتحديث الواجهات. يمكن لمؤلفي المكتبة إضافة أعضاء جدد وتنفيذهم افتراضيًا


يسمح التنفيذ الافتراضي للواجهات للمطورين بتحديث الواجهة ، مع السماح للمطورين الآخرين بتجاوز هذا التطبيق. يمكن لمستخدمي المكتبة قبول التطبيق الافتراضي كتغيير غير حرج.


تحديث باستخدام أعضاء الواجهة الافتراضية


وافق الفريق على التنفيذ الافتراضي على الأرجح: خصم على ولاء العملاء.


يجب أن يكون التحديث وظيفيًا لإعداد خاصيتين: عدد الطلبات المطلوبة للحصول على خصم ، والنسبة المئوية للخصم. هذا يجعله البرنامج النصي المثالي لأعضاء الواجهة الافتراضية. يمكنك إضافة طريقة إلى واجهة ICustomer وتوفير تنفيذها على الأرجح. يمكن تنفيذ جميع التطبيقات الحالية وأي تطبيقات جديدة بشكل افتراضي أو يكون لها إعداداتها الخاصة.


أولاً أضف طريقة جديدة للتنفيذ:


 //  1: public decimal ComputeLoyaltyDiscount() { DateTime TwoYearsAgo = DateTime.Now.AddYears(-2); if ((DateJoined < TwoYearsAgo) && (PreviousOrders.Count() > 10)) { return 0.10m; } return 0; } 

كتب مؤلف المكتبة أول اختبار للتحقق من التنفيذ:


 SampleCustomer c = new SampleCustomer("customer one", new DateTime(2010, 5, 31)) { Reminders = { { new DateTime(2010, 08, 12), "childs's birthday" }, { new DateTime(1012, 11, 15), "anniversary" } } }; SampleOrder o = new SampleOrder(new DateTime(2012, 6, 1), 5m); c.AddOrder(o); o = new SampleOrder(new DateTime(2103, 7, 4), 25m); c.AddOrder(o); //  : ICustomer theCustomer = c; Console.WriteLine($"Current discount: {theCustomer.ComputeLoyaltyDiscount()}"); 

انتبه إلى الجزء التالي من الاختبار:


 //  : ICustomer theCustomer = c; Console.WriteLine($"Current discount: {theCustomer.ComputeLoyaltyDiscount()}"); 

هذا الجزء ، من SampleCustomer إلى ICustomer مهم. SampleCustomer ألا توفر الفئة SampleCustomer تطبيقًا لحساب ComputeLoyaltyDiscount ؛ يتم توفير ذلك من خلال واجهة ICustomer . ومع ذلك ، SampleCustomer ترث فئة SampleCustomer أعضاء من SampleCustomer . هذه القاعدة لم تتغير. للاتصال بأي طريقة يتم تنفيذها في واجهة ، يجب أن يكون المتغير نوع واجهة ، في هذا المثال ICustomer .


البارامترات


هذه بداية جيدة. لكن التنفيذ الافتراضي محدود للغاية. يمكن للعديد من مستهلكي هذا النظام اختيار عتبات مختلفة لعدد المشتريات أو فترات عضوية مختلفة أو تخفيضات مختلفة في المئة ، ويمكنك تحسين عملية الترقية لمزيد من العملاء من خلال توفير وسيلة لتعيين هذه المعلمات. دعنا نضيف طريقة ثابتة تحدد هذه المعلمات الثلاث التي تتحكم في التطبيق الافتراضي:


 //  2: public static void SetLoyaltyThresholds( TimeSpan ago, int minimumOrders = 10, decimal percentageDiscount = 0.10m) { length = ago; orderCount = minimumOrders; discountPercent = percentageDiscount; } private static TimeSpan length = new TimeSpan(365 * 2, 0,0,0); // two years private static int orderCount = 10; private static decimal discountPercent = 0.10m; public decimal ComputeLoyaltyDiscount() { DateTime start = DateTime.Now - length; if ((DateJoined < start) && (PreviousOrders.Count() > orderCount)) { return discountPercent; } return 0; } 

تُظهر هذه الشفرة الصغيرة الكثير من الميزات اللغوية الجديدة. يمكن أن تتضمن الواجهات الآن أعضاء ثابتة ، بما في ذلك الحقول والأساليب. وشملت أيضا مختلف المعدلات الوصول. الحقول الإضافية خاصة ، والطريقة الجديدة عامة. أي من المعدلات مسموح لأعضاء الواجهة.


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


 ICustomer.SetLoyaltyThresholds(new TimeSpan(30, 0, 0, 0), 1, 0.25m); Console.WriteLine($"Current discount: {theCustomer.ComputeLoyaltyDiscount()}"); 

تمديد التنفيذ الافتراضي


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


النظر في بدء التشغيل الذي يريد جذب عملاء جدد. أنها توفر خصم 50 ٪ على الطلب الأول من عميل جديد. يحصل العملاء الحاليون على خصم قياسي. يحتاج مؤلف المكتبة إلى نقل التطبيق الافتراضي إلى الأسلوب protected static حتى يتمكن أي فصل يقوم بتنفيذ هذه الواجهة من إعادة استخدام الرمز في تنفيذه. يستدعي التنفيذ الافتراضي لعضو واجهة هذا الأسلوب العام:


 public decimal ComputeLoyaltyDiscount() => DefaultLoyaltyDiscount(this); protected static decimal DefaultLoyaltyDiscount(ICustomer c) { DateTime start = DateTime.Now - length; if ((c.DateJoined < start) && (c.PreviousOrders.Count() > orderCount)) { return discountPercent; } return 0; } 

عند تنفيذ الفصل الذي ينفذ هذه الواجهة ، يمكنك الاتصال يدويًا بطريقة المساعد الثابت وتوسيع هذا المنطق لتوفير خصم "للعميل الجديد":


 public decimal ComputeLoyaltyDiscount() { if (PreviousOrders.Any() == false) return 0.50m; else return ICustomer.DefaultLoyaltyDiscount(this); } 

يمكنك أن ترى كل الشفرة النهائية في مستودعنا على جيثب .


هذه الميزات الجديدة تعني أنه يمكن تحديث الواجهات بأمان إذا كان هناك تطبيق افتراضي مقبول للأعضاء الجدد. تصميم واجهات بعناية للتعبير عن الأفكار الوظيفية الفردية التي يمكن تنفيذها من قبل عدة فئات. هذا يجعل من السهل تحديث تعريفات الواجهة هذه عندما يتم العثور على متطلبات جديدة لنفس الفكرة الوظيفية.

Source: https://habr.com/ru/post/ar456232/


All Articles