English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
الحدث هو إخطار يرسله الكائن لتمثيل حدوث عملية. تتبع الأحداث في .NET نموذج تصميم المراقب.
الفئة التي تنشأ الحدث تسمى Publisher (ناشر)، الفئة التي تتلقي الإخطارات تسمى Subscriber (مشترك). يمكن أن يكون هناك عدة مشتركين للحدث الواحد. عادةً، ينشأ الناشر حدثًا عند تنفيذ عملية معينة. يجب على المشتركين الحصول على إخطار عند تنفيذ العملية، لذا يجب عليهم التسجيل في الحدث وتعالجه.
في C#، الحدث هو وكل مدمج. وهو يعتمد على الوكل. الوكل يحدد اسم المفوت (signature) لمتدخل الحدث في فئة المشترك(subscriber).
الشكل التالي يوضح الأحداث في C#.
إعلان الحدث في الفئة وتوليده، ويتم ربطه بمستمعي الحدث باستخدام الوكلات في نفس الفئة أو في فئة أخرى. الفئة التي تحتوي على الحدث تستخدم ناشر(publisher) فئة. الفئات الأخرى التي تستقبل هذا الحدث تسمى فئة المشترك(subscriber). يتم استخدام الحدث ناشر-مشترك(publisher-subscriber) نموذج.
ناشر(publisher)- هو عنصر يحتوي على تعريفات الأحداث والوكلات. ويتم تعريف علاقة الأحداث والوكلات في هذا العنصر. يتم استدعاء هذا الحدث من قبل كائنات فئة الناشر(publisher) ويتم إخطار الكائنات الأخرى.
المشترك(subscriber)- هو مجرد كائن يقبل الحدث ويقدم معالج الحدث. يتم استدعاء دالة الديليجيت في كلاس المُصدِر (publisher) من دالة معالج الحدث في كلاس الـ subscriber.
يمكن إعلان حدث من خلال خطوتين:
إعلان الديليجيت
استخدام كلمة المفتاح event لإعلان متغير الديليجيت
يظهر المثال التالي كيفية إعلان الحدث في كلاس المُصدِر.
public delegate void Notify(); // ديليجيت public class ProcessBusinessLogic { public event Notify ProcessCompleted; // حدث }
في المثال السابق، تم إعلان دالة Notify، ثم تم إعلان حدث ProcessCompleted من نوع دالة Notify في كلاس ProcessBusinessLogic باستخدام كلمة المفتاح "event". لذلك، يُدعى كلاس ProcessBusinessLogic بمُصدِر (publisher). تحدد دالة Notify توقيع معالج الحدث لحدث ProcessCompleted. يحدد توقيع Notify أن طريقة معالج الحدث في كلاس subscriber يجب أن تكون من نوع void وأن لا تحتوي على أي معاملات.
الآن، دعونا نرى كيف يمكن تحفيز حدث ProcessCompleted. انظر إلى التنفيذ التالي.
public delegate void Notify(); // ديليجيت public class ProcessBusinessLogic { public event Notify ProcessCompleted; // حدث public void StartProcess() { Console.WriteLine("بدأ عملية!"); // بعض الكود هنا.. OnProcessCompleted(); } protected virtual void OnProcessCompleted() // طريقة محمية افتراضية { // إذا كان ProcessCompleted غير null، يتم استدعاء الديليجيت ProcessCompleted?.Invoke(); } }
في الجزء السابق، يتم استدعاء طريقة StartProcess() في نهاية دالة onProcessCompleted()، مما سيؤدي إلى إطلاق حدث. عادةً، لتحفيز الحدث، يجب استخدام اسم الطريقة المحددة على <EventName> لتعريف الطريقة المحمية والافتراضية. تجعل المحمية والافتراضية من الممكن للفروع التغيير في منطق تحفيز الحدث. ولكن يجب على الفروع دائمًا استدعاء طريقة On<EventName> من الكلاس الأساسي، لضمان أن يتلقى الديليجيت المسجل الحدث.
يستخدم طريقة OnProcessCompleted() دالة ProcessCompleted?.invoke() لندعو الديليجيت. هذا سيندد لكل من تم تسجيله في حدث ProcessCompleted للحصول على طرق معالجة الحدث.
المشتركون في الخدمة يجب أن يتم تسجيلهم في الحدث ProcessCompleted، وأن يستخدموا الطريقة التي تتطابق مع التوقيع Notify من الديليجيت لمعالجته، كما هو موضح أدناه.
class برنامج { public static void الرئيسي() { ProcessBusinessLogic بل = new ProcessBusinessLogic(); bl.ProcessCompleted += bl_ProcessCompleted; // تسجيل الحدث bl.StartProcess(); } // معالج الحدث public static void bl_ProcessCompleted() { Console.WriteLine("Process Completed!"); } }
في هذا المثال، كلاس Program هو ProcessCompleted مشتركو الحدث. يستخدم محرر + = للتسجيل في الحدث. تذكر أن هذا هو نفس الطريقة التي نضيف فيها إلى قائمة النداءات في التفويض المتعدد. يعالج طريقة bl_processcompleted () الحدث لأنها تتطابق مع توقيع Notify.
.NET Framework يحتوي على أنواع تفويض مدمجة تستخدم لحدث شائع هي EventHandler و EventHandler <TEventArgs>. عادةً، أي حدث يجب أن يشمل إثنين من المعلمات: مصدر الحدث وبيانات الحدث. يتم استخدام واجهة التفويض EventHandler لجميع الحوادث التي لا تحتوي على بيانات حدث. بالنسبة للحوادث التي تحتوي على بيانات يجب على المرسل، يتم استخدام واجهة التفويض EventHandler<TEventArgs>.
يمكن استخدام واجهة التفويض EventHandler في المثال المبين أعلاه دون الحاجة إلى إعلان واجهة التفويض Notify مخصصة، كما هو موضح أدناه.
class برنامج { public static void الرئيسي() { ProcessBusinessLogic بل = new ProcessBusinessLogic(); bl.ProcessCompleted += bl_ProcessCompleted; // تسجيل الحدث bl.StartProcess(); } // معالجة الحدث public static void bl_ProcessCompleted(object sender, EventArgs e) { Console.WriteLine("Process Completed!"); } } public class ProcessBusinessLogic { // استخدام دالة التحويل المدمجة لتحديد الحدث public event EventHandler ProcessCompleted; public void StartProcess() { Console.WriteLine("بدأ عملية!"); // بعض الكود هنا.. OnProcessCompleted(EventArgs.Empty); // لا توجد بيانات حدث } protected virtual void OnProcessCompleted(EventArgs e) { ProcessCompleted?.Invoke(this, e); } }
في المثال السابق، يحتوي واجهة برمجة التطبيقات bl_ProcessCompleted() على إثنين من المعلمات التي تتطابق مع EventHandler. في نفس الوقت، يتم نقل this كمرسل و EventArgs. عندما نستخدم Invoke() في طريقة OnProcessCompleted() لتفجير الحدث، يكون فارغًا. لأن حادثنا لا يحتاج إلى أي بيانات، إنه فقط يخبر المشتركين بأن العملية قد اكتملت، لذا قمنا بتسليم EventArgs.Empty.
تسلم معظم الأحداث بعض البيانات إلى المشتركين. EventArgs هي فئة أساسية لجميع فئات بيانات الأحداث. يحتوي .NET على العديد من فئات بيانات الأحداث المدمجة، مثل SerialDataReceivedEventArgs. يتبع نمط الاسم ينتهي بEventArgs لجميع فئات بيانات الأحداث. يمكنك إنشاء فئات بيانات حدث مخصصة عن طريق ميراث EventArgs.
استخدم EventHandler <TEventArgs> لنقل البيانات إلى المعالج، كما هو موضح أدناه.
class برنامج { public static void الرئيسي() { ProcessBusinessLogic بل = new ProcessBusinessLogic(); bl.ProcessCompleted += bl_ProcessCompleted; // تسجيل الحدث bl.StartProcess(); } // معالجة الحدث public static void bl_ProcessCompleted(object sender, bool IsSuccessful) { Console.WriteLine("Process " + (IsSuccessful ? "Completed Successfully" : "failed")); } } public class ProcessBusinessLogic { // استخدام دالة التحويل المدمجة لتحديد الحدث public event EventHandler<bool> ProcessCompleted; public void StartProcess() { try { Console.WriteLine("بدأ عملية!"); // بعض الكود هنا.. OnProcessCompleted(true); } catch(Exception ex) { OnProcessCompleted(false); } } protected virtual void OnProcessCompleted(bool IsSuccessful) { ProcessCompleted?.Invoke(this, IsSuccessful); } }
في المثال السابق، نقلنا قيمة بولية واحدة إلى المعالج لتحديد ما إذا كان العملية قد انتهت بنجاح.
إذا كنت ترغب في نقل قيم متعددة كبيانات حدث، يمكنك إنشاء فئة مكتسبة من النوع الأساسي EventArgs، مثلما هو موضح أدناه.
class ProcessEventArgs : EventArgs { public bool ناجح { get; set; } public DateTime وقتإنهاء { get; set; } }
في المثال التالي، يُظهر كيفية نقل ProcessEventArgs 类 المخصصة إلى المعالج.
class برنامج { public static void الرئيسي() { ProcessBusinessLogic بل = new ProcessBusinessLogic(); bl.ProcessCompleted += bl_ProcessCompleted; // تسجيل الحدث bl.StartProcess(); } // معالجة الحدث public static void bl_ProcessCompleted(object sender, ProcessEventArgs e) { Console.WriteLine("عملية " + (e.IsSuccessful ? "نجحت" : "فشلت")); Console.WriteLine("وقت الانهاء: " + e.CompletionTime.ToLongDateString()); } } public class ProcessBusinessLogic { // استخدام دالة التحويل المدمجة لتحديد الحدث public event EventHandler<ProcessEventArgs> ProcessCompleted; public void StartProcess() { var data = new ProcessEventArgs(); try { Console.WriteLine("بدأ عملية!"); // بعض الكود هنا.. data.IsSuccessful = true; data.CompletionTime = DateTime.Now; OnProcessCompleted(data); } catch(Exception ex) { data.IsSuccessful = false; data.CompletionTime = DateTime.Now; OnProcessCompleted(data); } } protected virtual void OnProcessCompleted(ProcessEventArgs e) { ProcessCompleted?.Invoke(this, e); } }
لذلك، يمكنك إنشاء، إطلاق، تسجيل وتعامل بالأحداث في C#.
حدث هو طُبق للوكلات. هذا يعتمد على الوكلة.
يُستخدم كلمة المفتاح "event" مع متغير نوع التحويل لتحديد الحدث.
يُستخدم دالة التحويل المدمجةEventHandler أوEventHandler <TEventArgs> مُستخدمة للحدث الشائع.
المُنظم يُطلق أحداثًا، بينما يُسجل المُشترك أحداثًا ويقدم طريقة معالجة أحداث.
أسمِ طريقة إطلاق الحدث بنفس اسم الحدث، ويجب أن تبدأ بالنطق On.
يجب أن تكون إشارة طريقة المعالج متطابقة مع إشارة الوكلاء.
سجـل الحدث باستخدام عمـلة + =. استخدم -= لسحب الاشتراك، لا يمكن استخدام =.
تمرير بيانات المناسبة باستخدام EventHandler <TEventArgs>.
توليد فئة EventArgs الأساسية لإنشاء فئة بيانات مناسبة مخصصة.
يمكن إعلان المناسبة كمتوقفة، افتراضية، محكمة، أو مجردة (static, virtual, sealed, abstract).
يمكن للواجهة أن تحتوي على مناسبات كأعضاء.
إذا كان هناك متابعون متعددون، فإن معالج الحدث سيتم استدعاؤه بشكل متزامن.