شما می تونید برای هر کلاس یک یا تعدادی Event تعریف کنید که این eventها در شرایطی خاص اجرا می شوند. تعریف و استفاده از eventها به طور مستقیم به مبحث delegateها ارتباط دارند. در اینجا با نحوه تعریف و استفاده از eventها آشنا خواهیم شد.
در این تصویر، delegate پل ارتباطی دختر بچه و پدرش است. دختر بچه به عنوان یک Event Raiser، اطلاعات خود که تحت عنوان EventArgs می باشد را به سمت پدرش که یک Event Handler است، ارسال می کند.
رویدادها وظیفه اطلاع رسانی یا آگاه سازی را دارند و روشی هستند برای اعلام کردن رخداد یک اتفاق.
هر رویداد اطلاعات خاص خودش را دارد که در قالب EventArgs و از طریق delegate حمل خواهد شد.
یک مسیر ارتباطی بین event و event handler می باشد که به آن function pointer هم گفته می شود. به متدهایی اشاره می کند که دارای ورودی و خروجی یکسان می باشند. اطلاعات رویداد از این طریق منتقل می شوند.
مسئولیت دریافت و پردازش اطلاعاتی را دارد که از طریق delegate به آن رسیده است. معمولا دو ورودی Sender و EventArgs را دریافت می کند. (EventArgs مسئولیت کپسوله سازی اطلاعات را دارد).
برای تعریف delegate دلخواه خود، باید از کلمه کلیدی delegate استفاده کنیم و همچنین مشخص می کنیم که چه متدهای از لحاظ امضا و نوع خروجی قابلیت متصل شدن به آن را دارند.
public delegate void ShowMessageDelegate(string message);
در مثال بالا delegate تعریف شده به متدهایی می تواند متصل شود که void باشند و دارای یک ورودی string نیز می باشند.
برای این مثال، اگر از delegate خود یک نمونه تعریف کنیم، از ما نام یک متد را در ورودی دریافت می کند که دارای خروجی نمی باشد و یک ورودی string دریافت می کند.
static void Main(string[] args) { ShowMessageDelegate delegate1 = new ShowMessageDelegate(print); delegate1("normal delegate"); Console.ReadKey(); } private static void print(string message) { Console.WriteLine(message); }
یک delegate می تواند به چندین متد متصل شود و متدها به ترتیبی که به Invocation List اضافه شدند، اجرا خواهند شد.
static void Main(string[] args) { ShowMessageDelegate delegate1 = new ShowMessageDelegate(print1); ShowMessageDelegate delegate2 = new ShowMessageDelegate(print2); delegate1 += delegate2; delegate1("multicast delegate"); Console.ReadKey(); } private static void print1(string message) { Console.WriteLine($"print1 {message}"); } private static void print2(string message) { Console.WriteLine($"print2 {message}"); }
برای تعریف event از کلمه کلیدی event استفاده می کنیم و سپس delegate مورد نظر را که قبلا تعریف کرده ایم، مشخص می کنیم.
زمانی که بخواهیم یک event را فراخوانی و اجرا کنیم می توانیم مثل یک متد معمولی آن را فراخوانی کنیم و یا از طریق delegate فراخوانی شود.
بصورت پیش فرض برای خیلی از eventها استفاده می شود. اما برای داشتن اطلاعات شخصی سازی شده، راه حل آن است که از آن ارث بری کنیم.
مثال:
من یک کلاس به نام Worker ایجاد می کنیم که دارای دو event با نام های WorkPerformed و WorkCompleted می باشد. (برای WorkCompleted از delegate خود دات نت استفاده می کنم زیرا خروجی ندارم).
همچنین پارامتر های خود را در قالب کلاس WorkPerformedEventArgs ارسال می کنم. این کلاس از EventArgs مشتق شده است.
public class Worker { public string Title { get; set; } public event WorkPerformedDelegate<WorkPerformedEventArgs> WorkPerformed; public event EventHandler WorkCompleted; public void DoWork(int hour, string workType) { for (int i = 0; i < hour; i++) { System.Threading.Thread.Sleep(2000); OnWorkPerformed(i + 1, workType); } OnWorkCompleted(); } protected void OnWorkPerformed(int hour, string workType) { var del = WorkPerformed as WorkPerformedDelegate<WorkPerformedEventArgs>; if (del != null) { del(this, new WorkPerformedEventArgs(hour, workType)); } } protected void OnWorkCompleted() { var del = WorkCompleted as EventHandler; if (del != null) { del(this, EventArgs.Empty); } } }
public class WorkPerformedEventArgs : EventArgs { public WorkPerformedEventArgs(int hour, string workType) { Hour = hour; WorkType = workType; } public int Hour { get; set; } public string WorkType { get; set; } } public delegate bool WorkPerformedDelegate<TEventArgs>(object sender,TEventArgs eventArgs);
و برای استفاده، دو eventHandler با نام های DoingWork و WorkDone ایجاد می کنیم.
class Program { static void Main(string[] args) { Worker w1 = new Worker(); w1.Title = "Mohsen" ; w1.WorkPerformed += DoingWork; w1.WorkCompleted += WorkDone; w1.DoWork(7, "Designing"); Console.ReadKey(); } }
private static void WorkDone(object sender, EventArgs e) { Console.WriteLine($"Sender : {sender} : Work is Done !"); } private static bool DoingWork(object sender, WorkPerformedEventArgs e) { var w = sender as Worker; Console.WriteLine($"Sender : {w.Title} Work : {e.WorkType} Hour : {e.Hour}" ); return true; }
همچنین می توانیم eventHandlerها را به صورت Anonymous Method تعریف کنیم.
Worker w1 = new Worker(); w1.WorkPerformed += (s, e) => { Console.ForegroundColor = ConsoleColor.DarkBlue; Console.WriteLine("Hours Worked : " + e.Hour + " Work Type : " + e.WorkType); return true; }; w1.WorkCompleted += (s, e) => Console.WriteLine("Khaste Nabashid :-)"); w1.DoWork(5, "Designing");
پایان