با عرض سلام و وقت بخیر خدمت کاربران سایت پی وی لرن ، با دوره کامل آموزش #C در خدمت شما دوستان هستیم. در بخش قبلی با Delegate ها و کاربرد آنها در زبان #C آشنا شدید. در این بخش در مورد رویدادها در #C و نحوه تعریف رویداد در سی شارپ صحبت می کنیم. به طور کلی، رویداد چیزی ویژه ای است که اتفاق می افتد. به عنوان مثال، مایکروسافت وقایع را برای برنامه نویسان راه اندازی می کند تا آنها را در مورد ویژگی های محصولات جدید یا موجود آگاهی یابند.
مایکروسافت توسعه دهندگان را در مورد این رویداد از طریق ایمیل یا سایر گزینه های تبلیغاتی مطلع می کند. بنابراین در این مورد، مایکروسافت یک ناشر است که یک رویداد را راه اندازی می کند و برنامه نویس ها را در مورد آن اعلام می کند و توسعه دهندگان مشترکین این رویداد هستند و در رویداد شرکت می کنند.
رویدادهای #C از یک مفهوم مشابه پیروی می کنند. یک رویداد دارای publisher, subscriber, notification و یک handler است.
به طور کلی، کنترل های UI از وقایع گسترده استفاده می کنند. به عنوان مثال، کنترل دکمه در یک فرم در ویندوز دارای رویدادهای متعددی مانند click, mouseover و … است.
یک کلاس سفارشی همچنین می تواند یک رویداد برای اطلاع رسانی به سایر کلاس های مشترک در مورد چیزی که اتفاق افتاده است یا اتفاق می افتد داشته باشد .
بیایید ببینیم چگونه می توان یک رویداد را تعریف کرد و به سایر کلاس ها اطلاع داده می شود.
یک رویداد چیزی جز یک delegate محصور نشده (encapsulated) است. همانگونه که در بخش قبلی یاد گرفته ایم، یک delegate یک نوع داده ارجاعی است. شما می توانید این delegate را به صورت زیر نشان دهید:
1 2 3 | public delegate void someEvent(); public someEvent someEvent; |
اکنون، برای اعلام یک رویداد، قبل از اعلام یک متغیر از نوع delegate ، از کلمه کلیدی event، مانند مثال زیر استفاده کنید:
1 2 3 | public delegate void someEvent(); public event someEvent someEvent; |
اکنون، بیایید نمونه عملی یک رویداد را ببینیم. کلاس PrintHelper زیر را که اعداد صحیح را در فرمت های مختلف مانند شماره، پول، دهدهی، درجه حرارت و هگزادسیمال چاپ می کند، در نظر بگیرید. قبل از چاپ اعداد ، رویداد beforePrintEvent اجراء می شود :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | public class PrintHelper { // declare delegate public delegate void BeforePrint(); //declare event of type delegate public event BeforePrint beforePrintEvent; public PrintHelper() { } public void PrintNumber(int num) { //call delegate method before going to print if (beforePrintEvent != null) beforePrintEvent(); Console.WriteLine("Number: {0,-12:N0}", num); } public void PrintDecimal(int dec) { if (beforePrintEvent != null) beforePrintEvent(); Console.WriteLine("Decimal: {0:G}", dec); } public void PrintMoney(int money) { if (beforePrintEvent != null) beforePrintEvent(); Console.WriteLine("Money: {0:C}", money); } public void PrintTemperature(int num) { if (beforePrintEvent != null) beforePrintEvent(); Console.WriteLine("Temperature: {0,4:N1} F", num); } public void PrintHexadecimal(int dec) { if (beforePrintEvent != null) beforePrintEvent(); Console.WriteLine("Hexadecimal: {0:X}", dec); } } |
PrintHelper یک کلاس ناشر است که رویداد beforePrint را منتشر می کند. توجه داشته باشید که در هر روش چاپ، ابتدا بررسی می کند که آیا beforePrintEvent دارای مقدار خالی نیست و سپس آن را صدا میزند.
beforePrintEvent یک شی از نماینده (delegate) BeforPrint است، بنابراین اگر یک کلاس در رویداد به اشتراک گذاشته (Subscribed) نشود ، Null خواهد بود و به همین دلیل لازم است قبل از فراخوانی یک delegate مقدار آن بررسی شود که null نباشد.
حالا، اجازه دهید یک subscriber ایجاد کنیم. به عنوان مثال کلاس ساده زیر را در نظر بگیرید:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | class Number { private PrintHelper _printHelper; public Number(int val) { _value = val; _printHelper = new PrintHelper(); //subscribe to beforePrintEvent event _printHelper.beforePrintEvent += printHelper_beforePrintEvent; } //beforePrintevent handler void printHelper_beforePrintEvent() { Console.WriteLine("BeforPrintEventHandler: PrintHelper is going to print a value"); } private int _value; public int Value { get { return _value; } set { _value = value; } } public void PrintMoney() { _printHelper.PrintMoney(_value); } public void PrintNumber() { _printHelper.PrintNumber(_value); } } |
تمام مشترکین (subscribers) باید یک تابع handler را فراهم کنند، که وقتی یک ناشر یک رویداد را ایجاد می کند، فراخوانی می شود.
در مثال بالا، کلاس Number یک نمونه از PrintHelper را ایجاد می کند و با عملگر “=+” beforePrintEvent را به اشتراک می گذارد و نام تابع را که رویداد را اداره می کند (در هنگام انتشار یک رویداد را فراخوانی می کند) printHelper_beforePrintEvent قرار می دهد.
حالا، نمونه ای از کلاس Number و متد های چاپ را ایجاد می کنیم:
1 2 3 | Number myNumber = new Number(100000); myNumber.PrintMoney(); myNumber.PrintNumber(); |
خروجی :
1 2 3 4 | BeforePrintEventHandler: PrintHelper is going to print value Money: $ 1,00,000.00 BeforePrintEventHandler: PrintHelper is going to print value Number: 1,00,000 |
تصویر زیر مدل کلی رویداد را توضیح می دهد:
رویدادها همچنین می توانند داده ها را بعنوان یک argument به subscribed خودشان منتقل کنند. یک رویداد argument را به عنوان یک delegate signature به handler منتقل می کند .
در مثال زیر PrintHelper نماینده (delegate) BeforePrint را که یک آرگومان رشته را می پذیرد، اعلام می کند. بنابراین اکنون می توانید یک رشته را – هنگامی که رویدادی از PrintNumber یا هر متد چاپ دیگر فراخوانی می شود – ، منتقل کنید.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | public class PrintHelper { public delegate void BeforePrint(string message); public event BeforePrint beforePrintEvent; public void PrintNumber(int num) { if (beforePrintEvent != null) beforePrintEvent.Invoke("PrintNumber"); Console.WriteLine("Number: {0,-12:N0}", num); } public void PrintDecimal(int dec) { if (beforePrintEvent != null) beforePrintEvent("PrintDecimal"); Console.WriteLine("Decimal: {0:G}", dec); } public void PrintMoney(int money) { if (beforePrintEvent != null) beforePrintEvent("PrintMoney"); Console.WriteLine("Money: {0:C}", money); } public void PrintTemperature(int num) { if (beforePrintEvent != null) beforePrintEvent("PrintTemerature"); Console.WriteLine("Temperature: {0,4:N1} F", num); } public void PrintHexadecimal(int dec) { if (beforePrintEvent != null) beforePrintEvent("PrintHexadecimal"); Console.WriteLine("Hexadecimal: {0:X}", dec); } } |
حالا، کلاس subscriber باید دارای یک event handler باشد که پارامتر رشته دارد.
در مثال زیر کلاس Number دارای تابع printHelper_beforePrintEvent با پارامتر string است.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | class Number { private PrintHelper _printHelper; public Number(int val) { _value = val; _printHelper = new PrintHelper(); //subscribe to beforePrintEvent event _printHelper.beforePrintEvent += printHelper_beforePrintEvent; } //beforePrintevent handler void printHelper_beforePrintEvent(string message) { Console.WriteLine("BeforePrintEvent fires from {0}",message); } private int _value; public int Value { get { return _value; } set { _value = value; } } public void PrintMoney() { _printHelper.PrintMoney(_value); } public void PrintNumber() { _printHelper.PrintNumber(_value); } } |
1 2 3 4 | BeforePrintEvent fires from PrintMoney. Money: $ 1,00,000.00 BeforePrintEvent fires from PrintNumber. Number: 1,00,000 |
در این بخش با رویداد ها و نحوه تعریف رویدادهای سفارشی در زبان #C آشنا شدید.
در بخش بعدی قصد داریم در رابطه با Generic ها در زبان #C صحبت کنیم.
مهدی
سلام، مثال آخری که نوشتین با کد های html قاطی شده لطفا درستش کنید، ممنون
صادق
سلام. با تشکر از اطلاع رسانی شما. آموزش اصلاح شد.