خوش برگشتید.
تو این ویدیو قراره از **generic delegate**، یعنی **EventHandler** استفاده کنیم.
خب، کلمات زیادی اینجا هست، درسته؟
ما می‌دونیم **delegate** چیه.
و هنوز نمی‌دونیم **EventHandler** چیه، و نه **TEventArgs** چی هستن.
قبلاً کلمه **generic** رو شنیدیم، اما بیایید ببینیم چرا این موضوع اهمیت داره.
پس اول از همه، چرا **Event Args** مهم هستن و اصلاً چی هستن؟
**Event Args** همون **Event Arguments** (آرگومان‌های رویداد) هستن.
خب، اساساً وقتی یک **event** **raise** (راه اندازی) می‌شه، شما گاهی اوقات می‌خواید اطلاعاتی درباره اون **event** ارسال کنید.
اول از همه، اون شخص یا **object**ای که **event** رو **raise** کرده کی بوده.
و دوماً، یک سری اطلاعات اضافی، یک سری **argument** (پارامتر) اضافی که می‌خواید به هر کسی که داره **event** رو مصرف می‌کنه، ارسال کنید.
یعنی به **subscriber**ها، چون **subscriber**ها، شاید به این اطلاعات نیاز داشته باشن، اطلاعاتی که مربوط به اون **event** هست و می‌خوان نمایشش بدن، یا بعداً باهاش کار کنن یا چیزی شبیه اون.
و برای دستیابی به این موضوع، باید از **Event Arguments** استفاده کنید.
و معمولاً چیزی که خواهید دید، این موارد هستن:
پس، این **delegate** **generic** به اسم **EventHandler** وجود داره. بیایید یک **public event** ایجاد کنیم و این یکی **EventHandler** خواهد بود.
این یکی اینجا.
در واقع، این یکی هست.
این **generic** (عمومی) هست.
پس اگه موس رو روش ببرید، می‌بینید که می‌گه **EventHandler object sender TEventArgs**. اوکی.
پس بیایید این رو بررسی کنیم.
پس تو این **EventHandler** می‌تونیم ببینیم چی می‌گه.
پس این **EventHandler** یک **delegate** هست، درسته؟
و می‌دونیم که برای آماده‌سازی **event**ها به **delegate**ها نیاز داریم.
حالا این **EventHandler** همچنین دو تا **argument** داره.
یکی از اونها **sender** (فرستنده) هست که از نوع **object** (قابل خالی بودن) هست. و اون یکی **EventArgs** هست.
خب، **EventArgs** فقط **base class** (کلاس پایه) برای **class**هایی هست که داده‌های **event** رو شامل می‌شن، و یک مقدار برای استفاده در **event**هایی که شامل داده‌های **event** نیستن، فراهم می‌کنه.
پس اگه می‌خواید **event** خودتون رو ایجاد کنید که بعداً داده هم به **subscriber**ها ارسال کنه، باید از **EventArgs** استفاده کنید.
حالا نکته جالب اینه که می‌تونید از **EventArgs** **inherit** (ارث‌بری) کنید، چون اگه به **EventArgs** نگاه کنیم،
می‌بینید که یک **public class** هست. **sealed** (مُهر و موم شده) نیست، پس می‌تونیم ازش ارث‌بری کنیم.
و زیر **class**های **EventArgs** زیادی وجود داره. پس **class**هایی که از **class EventArgs** ارث می‌برن.
خیلی ساده هست. همونطور که می‌بینید، **class EventArgs**،
تنها کاری که انجام می‌ده اینه که یک **static read only EventArgs** داره، که یک **EventArgs** خالی هست. و کار زیادی انجام نمی‌ده، درسته؟ اما وقتی اون رو برای کارهای خودمون استفاده می‌کنیم، خیلی قدرتمند می‌شه.
اوکی، بنابراین برای انجام این کار، بیایید با پیروی از این موضوع شروع کنیم.
پس بیایید **class EventArgs** سفارشی خودمون رو ایجاد کنیم.
بسیار خب، من اون رو اینجا بالا ایجاد می‌کنم.
پس می‌گم **public class TemperatureChangedEventArgs**. پس این نام **EventArgs** اینجا مهمه.
تا بدونیم این **class** داره از **EventArgs** **inherit** می‌کنه. این فقط یک روش معموله.
اوکی، پس حالا **class** خودمون داره از این **class EventArgs** ارث می‌بره و اون رو **extend** (گسترش) می‌ده، به این معنی که داره **functionality** (عملکرد) بهش اضافه می‌کنه. درسته.
پس اطلاعاتی که می‌خوام ذخیره کنم، قراره **temperature** (دما) باشه. و این یکی رو فقط می‌تونم **get**ش کنم. فقط می‌گم **set**ش نکن.
اوکی. پس این **TemperatureEventArgs**، و اگه بخوام دما رو **set** کنم، فقط می‌تونم اون رو تو **constructor** انجام بدم. پس **public TemperatureChangedEventArgs** که همون **constructor** هست. و دارم دما رو پاس می‌دم. و اون دما رو تو **object** مربوط به **EventArgs** ذخیره می‌کنم. پس **EventArgs** حالا دما رو نگهداری می‌کنه، اوکی.
پس هر وقت یک **object** ازش ایجاد می‌کنیم. پس این **constructor** و این **temperature property** هست. بسیار خب.
پس حالا که این **EventArgs** رو داریم، گام بعدی اینه که اونها رو داخل **TemperatureMonitor**مون استفاده کنیم.
چون می‌خوام هر وقت **event** رو **raise** می‌کنم، فقط یک **string message** پاس ندم. در واقع می‌خوام **TemperatureEventArgs** رو پاس بدم، هرچیزی که هست. پس حالا می‌تونم بگم:
**TemperatureChangedEventArgs**. و یک اسم رایج **E** هست، اوکی.
پس معمولاً وقتی از **EventArgs** استفاده می‌کنید، فقط **E** صداش می‌زنید.
پس حالا وقتی دما رو تغییر می‌دم، قراره **E** رو پاس بدم.
خب، این کار نمی‌کنه، چون متد ما اینجا، **event** **OnTemperatureChanged** ما، از **TemperatureChangeHandler** پیروی می‌کنه که انتظار یک **message** رو داره. انتظار یک نوع داده **EventArgs** رو نداره.
پس حالا قراره این کل موضوع رو تغییر بدیم. دیگه از این **delegate** استفاده نمی‌کنیم، به خاطر همینه که دیگه نمی‌تونیم از این خط استفاده کنیم.
به جای اون، قراره یک **generic EventHandler event** ایجاد کنیم. پس این یکی اینجا با **TemperatureChangedEventArgs**. و قراره اون رو **TemperatureChanged** صدا بزنیم. خب حالا این **EventHandler** باید قطعاً یک **event** باشه.
پس نیاز داریم کلمه کلیدی **event** رو اضافه کنیم.
و اگه بهش نگاه کنید، **EventHandler** فقط یک **delegate** هست، درسته؟ پس اساساً همون چیزیه که وقتی ما این **event** رو اینجا ایجاد کردیم، بود، که اون هم از **TemperatureChangeHandler** که یک **delegate** بود، پیروی می‌کرد.
اوکی، پس حالا فقط اینه که **EventHandler** یک **delegate** از پیش تعریف شده هست که حالا قراره **TemperatureChangeEventArgs** رو بپذیره. پس می‌بینید که از نوع **generic EventArgs** هست.
بنابراین معنی این **generic EventArgs** اینه که ما **generic** رو به طور کلی دیدیم، اما **generic EventArgs** فقط می‌گه هر نوع **EventArgs**ای. من اهمیتی نمی‌دم که **base class**، **EventArgs** هست یا هر چیزی که شما با ارث‌بری از **EventArgs** ساختید، که همون کاری هست که ما اینجا انجام دادیم.
اوکی، ما از **EventArgs** ارث بردیم، و حالا می‌تونیم از **TemperatureChangedEventArgs** برای **EventHandler**مون استفاده کنیم. اوکی.
و علاوه بر اون، چیزی که خواهید دید اینه که می‌گه: یک **sender** (فرستنده) به من بده و **EventArgs** رو به من بده.
پس هر وقت حالا بخوایم از **EventHandler**مون که اینجا استفاده می‌کنیم، استفاده کنیم، حالا متدی که تو **event** **TemperatureChanged** **subscribe** می‌شه، باید **object sender** و همچنین **TemperatureChangeEventArgs** **E** رو پاس بده، که حالا به این معنیه که باید بریم پایین به **subscriber**مون.
پس این در اینجا **subscriber** ماست.
و این **TemperatureAlert** این متد **OnTemperatureChanged** رو داره که حالا نیاز داره **object sender** و همچنین **TemperatureChangeEventArgs E** رو بپذیره.
و حالا اینجا می‌تونیم بگیم: **Alert**. و بذارید در واقع از **string manipulation** اینجا استفاده کنم. **Alert** و **temperature is** (دما هست) و بعد **E.** و **E** دما رو نگه می‌داره.
پس حالا این **Event Arguments object** اطلاعاتی درباره دما نگهداری می‌کنه.
چون اگه بهش نگاه کنیم، اگه به این **TemperatureChangedEventArgs** که ایجاد کردیم نگاه کنیم، این **property** به اسم **Temperature** رو داره. حالا بیایید اون رو گسترش بدیم و همچنین بگیم **sender** کی هست.
پس **sender is** (فرستنده هست) و بعد **sender**. و من فقط می‌گم **sender**، اوکی. پس این **sender** درست اینجا، اوکی.
حالا که این تغییر کرده، باید یک تغییر هم تو این قسمت اینجا ایجاد کنیم، اوکی.
پس حالا **RaiseTemperatureChangedEvent**، من این رو **OnTemperatureChanged** صدا می‌زنم و کاری که انجام می‌ده اینه که از **event** **TemperatureChanged** ما استفاده می‌کنه و اون رو با **this** و **E** **invoke** می‌کنه. پس چه اتفاقی تو این خط داره می‌افته؟
این یک خط فوق‌العاده باحاله، چون چیزی که داریم می‌گیم اینه که این **event** به اسم **TemperatureChanged** وجود داره. و به هر کسی، اگه هر کسی باشه، هر **subscriber**ای، من می‌خوام اون رو **invoke** کنم و می‌خوام شما رو **invoke** کنم.
من می‌خوام اساساً این متد رو برای تک تک **subscriber**ها صدا بزنم. پس این فقط یک **subscriber** یا **TemperatureAlert** هست، اما می‌تونه **subscriber**های دیگه هم باشه، به تک تک اونها.
می‌گم: هی، من قراره شما رو **invoke** کنم.
قراره متد شما **OnTemperatureChanged** رو حالا صدا بزنم، چون تو نقطه بعدی
می‌تونید اینجا ببینید که داریم اون رو اضافه می‌کنیم. پس اینجا بیایید اون رو به **TemperatureChanged** تغییر بدیم، چون این اسم جدیده، اگه بهش نگاه کنید، اسم **EventHandler** ما اینجا هست.
و بعد تو این خط اساساً داریم از این **TemperatureAlert** استفاده می‌کنیم. اگه یادتون باشه، این **object TemperatureAlert** هست. و تو این خط چیزی که داریم می‌گیم اینه که: اوکی، **event** **TemperatureChanged** حالا یک **listener** جدید داره. و **listener** یا **subscriber**، این متد **OnTemperatureChanged** هست و وقتی **event** **TemperatureChanged** **trigger** بشه، این متد رو صدا بزن.
پس این متد **OnTemperatureChanged** رو صدا بزن. کی **trigger** می‌شه؟ خب، این منطقیه که ما اینجا داخل **TemperatureMonitor**مون داریم که **event** رو **raise** می‌کنه، درسته؟ پس اینطوری ما **event** رو قبلاً **raise** می‌کردیم.
حالا می‌خوایم این متد رو تو لحظه درست صدا بزنیم.
پس کاری که قراره انجام بدم اینه که کد رو کمی تغییر بدم. قراره بگم هر بار که دما یک دمای جدید هست، قراره **event** رو **raise** کنیم.
پس هر بار که مقدار **temperature** برابر با مقداری که برای **set** کردن **temperature** پاس داده می‌شه، نیست. پس کجا داریم دما رو اینجا **set** می‌کنیم؟
اینجا جاییه که داریم دمای **TemperatureMonitor**مون رو **set** می‌کنیم. پس این **class** **TemperatureMonitor** هست، درسته؟
پس هر بار که داریم دما رو **set** می‌کنیم، برای مثال داریم اون رو از **API** می‌خونیم یا از یک **sensor** می‌خونیم. بررسی می‌کنیم که آیا دما یک دمای جدید هست یا نه.
و اگه هست، خب بیایید دمای جدید رو **set** کنیم. و علاوه بر اون، بیایید **event** رو هم **raise** کنیم.
پس قراره متد **OnTemperatureChanged**مون رو صدا بزنیم. و قراره **event** رو پاس بدیم. چطور می‌تونیم حالا **TemperatureChangeEventArgs E** رو پاس بدیم؟ خب، می‌تونیم یک **new TemperatureChangedEventArgs** ایجاد کنیم.
و می‌تونیم دما رو پاس بدیم. خب، می‌تونیم یا **value** رو پاس بدیم یا می‌تونیم **underscore temperature** رو هم پاس بدیم. تو این نقطه هر دو یکی هستن، درسته؟ چون ما دما رو با **value** بازنویسی کردیم. پس حالا چیزی که داریم می‌گیم، و این حالا همه چیز رو کنار هم میاره، هر وقت من دارم **event** رو **raise** می‌کنم، دارم به شما یک سری **EventArgs** می‌دم، تو این حالت فقط یکی، که دما هست.
پس بعدش فراخوانی واقعی متد. پس این اینجا مستقیماً داره این متد رو صدا می‌زنه. درسته.
اما بعدش، اما اینجا جاییه که داریم **event** رو **invoke** می‌کنیم و همه رو مطلع می‌کنیم، هر **subscriber**ای رو.
پس اینجا داریم می‌گیم که هر **subscriber**ای رو مطلع می‌کنیم.
و چی رو بهشون اطلاع می‌دیم؟ بهشون درباره **EventArgs** اطلاع می‌دیم، که تو این حالت فقط دما هست.
اما می‌تونه خیلی بیشتر باشه. می‌تونه خیلی اطلاعات بیشتری باشه.
حالا کاملاً در کنترل شماست.
و من همچنین **object**ای که **event** رو **invoke** کرده رو پاس می‌دم. پس **object**ای که **event** رو **raise** کرده. و اون چه **object**ای هست؟ این **this** هست. **this** چیه؟
این **class** **EventsApp.TemperatureMonitor** هست. پس اگه بیرون بریم، می‌بینیم که در واقع این **class** **TemperatureMonitor** هست. چون این کلمه کلیدی **this** تو بستر این **class** استفاده می‌شه.
پس این **class** هست. پس **object TemperatureMonitor** که داریم پاس می‌دیم. خود **class** نیست، بلکه **object** هست. چون اگه بهش نگاه کنیم، وقتی داریم دما رو **set** می‌کنیم، داریم اون رو تو **monitor** انجام می‌دیم. **monitor** کیه؟
این **class** **TemperatureMonitor** هست. پس این **class** درست اینجا هست. و این کلمه کلیدی **this** داخل **class** هست، پس فقط **object** رو پاس خواهد داد.
بیایید فقط تستش کنیم و خواهید دید که این درسته، اوکی. پس بذارید بهتون نشون بدم.
و ما اینجا هستیم: **Alert temperature is 20, sender is EventsApp.TemperatureMonitor**. پس می‌بینید که حالا **alert** ما هر بار که دما تغییر می‌کنه، فعال می‌شه. پس اگه دما رو مثلاً به 23 درجه تغییر بدیم، بعد می‌گه: **Temperature is 23, sender is EventsApp.TemperatureMonitor**.
پس **sender** که این **sender object** برای **subscriber** ما هست، مهم نیست **subscriber** کیه. می‌تونه مثلاً یک **subscriber** سوم یا پنجم باشه. می‌تونیم ده تا **subscriber** داشته باشیم.
بیایید یک **subscriber** دیگه فقط سریع کپی کنیم.
پس این یکی خواهد بود، مثلاً، **temp cooling alert** (هشدار خنک کننده دما). بسیار خب. و قراره همون کار رو انجام بده، و فقط می‌گه **temp cooling alert**. بسیار خب.
و حالا بیایید جلو بریم و اون **temp cooling alert** رو هم اضافه کنیم.
پس **temp cooling alert**، **alert two** (هشدار دو) **new temp cooling alert**.
و حالا **monitor** ما هم قراره **subscribe** کنه یا مثلاً **alert two** ما که همون **temp cooling alert** ماست، هم قراره تو **event** **TemperatureChanged** **monitor** **subscribe** کنه.
پس حالا اگه این رو اجرا کنیم، برای هر دوی اونها **trigger** می‌شه. پس می‌بینید که **sender** تو هر دو حالت **EventsApp.TemperatureMonitor** هست.
چون این نام **class** **object**ای هست که داره **event** رو **raise** می‌کنه، اوکی.
پس تو این نقطه، فکر می‌کنم کل موضوع رو گذروندیم.
حالا می‌دونید چطور می‌تونید اطلاعات خودتون رو پاس بدید، چطور می‌تونید **EventArgs** خودتون رو ایجاد کنید، به اصطلاح، تا جزئیات خودتون رو مثل دما یا هر پارامتر دیگه ای که می‌خواید داشته باشید، پاس بدید.
دیدید که چطور از **generic EventHandler** استفاده کنید، و دیدید که چطور **event**ها رو **raise** کنید و همچنین چطور **subscriber** داشته باشید. پس این **subscriber** دو هست.
و بعد چطور همه چیز رو کنار هم بیارید تا در واقع اون رو اجرا کنید، اوکی.
پس این برای این ویدیو کافیه.
طولانی‌ترین ویدیوی دوره تا الان.
اما من نمی‌تونستم اون رو تو ویدیوهای جداگانه بذارم.
چون هر بخش به تنهایی واقعاً بدون بخش‌های دیگه معنی نداشت. واقعاً مثل اینه که همه چیز به هم تعلق داره. اما حالا شما اون رو به دست آوردید.
تبریک می‌گم.