PDA

View Full Version : رویدادها در OOP وایجاد کلاس های رویداد در C#



Sajjad1364
شنبه 09 تیر 1386, 13:30 عصر
با سلام.

بیان مطالب برنامه نویسی شئ گرا بوسیله زبان عامیانه وطبیعی انسان بمراتب زیباتر و درک
جالبتری را بدست میدهد.از اینرو در حین جواب به دوستان دیگر و یا زدن پست جدید ,اگر به فلسفه وجودی هر عنصر در حیطه برنامه نویسی شئ گرا و ارتباطش با دنیای طبیعت نیز اشاراتی داشته باشیم در ذهن خواننده مطلب, از برنامه نویسی شئ گرا تصویری از واقعیات دنیای طبیعت که به دنیای برنامه نویسی راه پیدا کرده اند تشکیل می شود.کسانیکه در این تالار حضور دارند بایستی برای افراد تازه کار توضیح هرمسئله ای که در حیطه برنامه نویسی
شئ گرا می باشد را در سطح دنیای طبیعی بیان کنند و این وظیفه همه ما میباشد که
برنامه نویسی شئ گرا را طوری بیان کنیم که مستقل ازدنیای کامپیوتر وبرنامه نویسی باشد.
تا برنامه نویسان تازه کار خود را غرق در مباحث سخت و پیچیده نبینند.
در این تالار مباحث مختلفی مورد بحث و گفتگو می باشد ,اما چیزی که کمتر در مورد آن به برنامه نویسان عزیز اطلاع رسانی میشود ,خود برنامه نویسی شئ گراست.بیشتر پست ها سوالاتی هستند که از سوی برنامه نویس ها مطرح میشوند,اما اطلاع رسانی و ارائه مطالب
کمتر دیده میشود.از شما دوستان میخواهم ,سعی کنیم در حیطه برنامه نویسی شئ گرا بیشتر وارد شویم و تجربیات ارزشمندتان رادر اختیار دیگران بگذارید. همچنین توضیح هر عنصر شئ گرا را ابتدا در سطح دنیای طبیعت بیان کنیم.

تعامل سی شارپ و رویداد ها نیز از این مقوله جدا نیستند و آنها نیز باید همین روشها مورد توجه قرار بگیرند.
رویدادها در زبانهای برنامه نویسی از عناصری هستند که هم حضوری اتنزاعی و هم حضوری کاملا حیاتی و مشهود دارند.وجود رویدادها در زبان های غیر شئ گرا حیاتی و در زبانهای برنامه نویسی شئ گرا انتزاعی. در دنیای طبیعت که برنامه نویسی شئ گرا نیز از آن برگرفته شده است, رویداد و وجودشان انتزاع میباشد.در واقع رویدادها فقط جهت بیان آسانتر رفتارهای
اشیاء در مقابل پیغامهایی که از سوی اشیاء دیگر به آنها ارسال میشود ,وجود دارند.
به عنوان مثال شئ چوب و شئ شیشه را درنظر بگیرید. اگر با شئ چوب به شیشه ضربه ای وارد شود پیغام ضربه به شیشه ارسال میشود و شئ شیشه در مقابل این پیغام ممکن است رفتاری از خود بروز بدهد ویا ندهد.عدم پاسخ و یا پاسخ به این پیغام به شدت ضربه بستگی دارد.اگر شئ شیشه در مقابل پیغام چوب.ضربه() مقاوم باشد,از نظر ما عکس العملی از شیشه ایجاد نشده است اما حقیقت اینجاست که رفتاری درونی در مقابل این پیغام از سوی شئ شیشه انجام گرفته و چون ما آن را در غالب رویدادی برای شئ شیشه ندیده ایم پس وجود هرگونه عکس العملی را از سوی شئ شیشه انکار میکنیم.در حالیکه اگر پارامتر نیرو را افزایش بدهیم و شیشه بشکند اگر کسی بپرسد چه شدما فورا می گوییم شیشه شکست.
این رفتار ,رفتار ویژه ایست که شئ شیشه از خود بروز داد.بدلیل خاص بودن این رفتار ما برای بیان وضعیت شئ شیشه میگوییم شیشه شکست.این وضعیت ویژه در مقابل پیغام ضربه()
را رویداد یا Event می نامیم.در دنیای طبیعت تمامی اشیاء در مقابل پیغام هایی که در برابر آنها رفتاری برایشان تعریف نشده انعطاف پذیرند و ممکن است رفتاری از خود در مقابل آن پیغام بروز دهند.در حالیکه در مورد اشیاء دنیای برنامه نویسی این قضیه کاملا برعکس است و اشیاء دنیای برنامه نویسی به آندسته از پیغامهایی جواب می دهند ,که در درون خود رفتاری برای پاسخگویی به آن پیغام وجود داشته باشد.
وجود رویدادهای زیاد برای یک شئ نشان می دهد که شئ در مقابل دریافت پیغامی از شئ دیگر و پیش آمدن وضعیتی ویژه, رفتاری را که کاربر انتظار دارد از خود بروز میدهد.
مثلا اگر شئ Form1 در مقابل پیغام بسته شدن رویدادی برای ارایه به برنامه نویس نداشته باشد همیشه رفتار ثابتی از خود بروز می دهد.یعنی همیشه بسته میشود.ولی اگر رویدادی را برای این پیغام در نظر گرفته باشد میتواند رفتاری را که برنامه نویس انتظار دارد در مقابل آن پیغام از خود بروز دهد.از طرفی چون نمیتوان تمام وضعیت های ویژه و رویدادهای یک شئ را پیش بینی کرد ,پس اگر نقطه شروعی موجود نباشد نمیتوان برنامه ای را به اجرا درآورد.
به همین دلیل وجود متد اصلی Main و شروع برنامه از آنجا امری ضروریست و اگر زبانی به غیر از این مکانیزم را بکار ببرد ,بارگذاری اولیه را پنهانی انجام میدهد و اجرای هر گونه کدی وابسته به اتفاق افتادن یک رویداد می شود.(Visual Basic)
همچنین رویدادهایی وجود دارند که درصورت اتفاق افتادن وضعیت شئ رادر مقابل پاسخگویی به پیغامهای مختلف تعیین می کنند.این رویدادها , رویدادهای شئ گرای اشیاء محسوب میشوند و عدم وجود آنها در هر گونه عنصری آن عنصر را غیر شئ گرا میکند.مثلا رویداد EnabledChanged وقوع اتفاقی را خبر میدهد که بیانگر جواب دادن یا ندادن شئ به هرگونه پیغامیست .رفتاری که در مقابل این رویداد انجام میشود میبایست تحت کنترل باشد.

رویدادها بوسیله سه عنصر وابسته به هم فراهم میشوند.
1)کلاسی که داده رویداد را فراهم میکند.
2)یک Delegate برای رویداد
3)و کلاسی که رویداد را بالا می کشد(Raise می کند)
دات نت فریم ورک استانداردی را برای نامگذاری کلاس ها و متدهای مربوط به رویدادها دارد.
برای نوشتن کلاسی که بتواند رویدادی را بالا بکشد وداده ای را در خود داشته باشد به عناصر زیر احتیاج دارید.
1)کلاسی که داده های رویداد را نگه داری میکند و باید طوری نامگذاری شود که آخر نام کلاس

عبارت EventArgs باشد .مثلا MyEventEventArgs

2)کلاس جدید شما باید از کلاس System.EventArgs مشتق شود.

3)یک Delegate برای رویداد که آخر نام انخاب شده باید عبارت EventHandler باشد
مثلا MyEventEventHandler

نکته:کلاسی که رویداد را بالا میکشد ,کلاسی است که رویداد در آن اتفاق می افتد.
بعنوان مثال میتوان گفت که کلاس TextBox حاوی رویداد TextChanged میباشد.واین به این معناست که هر شئ ای از نوع TextBox که در آن رویداد TextChanged رخ می دهد ,آن شئ آن رویداد را Raise کرده است.
نکته:معمولا تعریف Delegate و کلاس حاوی داده های رویداد در داخل NameSpace اصلی نوشته میشوند.
مثال:برنامه ساده ای رادر نظر میگیریم .عددی از ورودی گرفته میشود اگر آن عدد کوچکتر از 100 بود از برنامه خارج و اگر بزرگتر از 100 بود رویداد greateNumber اتفاق می افتد و عدد وارد شده چاپ می گردد.


using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication2
{
class Program
{
private static event MyEventEventHandler greateNumber;
static void Main(string[] args)
{
greateNumber += new MyEventEventHandler(Program_greatNumber);
int a = int.Parse(Console.ReadLine());
if (a > 100 && greateNumber != null)
{
MyEventEventArgs m = new MyEventEventArgs(a.ToString());
greateNumber(new Program(), m);
}
}
static void Program_greatNumber(object sender, MyEventEventArgs e)
{
Console.WriteLine(e.Message);
}
}
public delegate void MyEventEventHandler(Object sender, MyEventEventArgs e);
public class MyEventEventArgs : System.EventArgs
{
public MyEventEventArgs(string m)
{
this.message = m;
}
private string message;
public string Message
{
get { return message; }
set { message = value; }
}
}
}


کلاسی که داده های رویداد را نگه داری میکند از خط 26 تا خط 38 قرار دارد.این کلاس که با نام
classMyEventEventArgs : System.EventArgs معرفی میشود از قواعد نامگذاری پیروی و همچنین از کلاس System.EventArgs مشتق میشود.
خط 25 نیز Delegate مورد نیاز را ایجاد میکند.اینDelegate دارای دو پارامتر است یکی از نوع Object و دیگری همیشه از نوع کلاس نگه داری کننده داده های رویداد می باشد

خط 8 حاوی تعریف رویداد مورد نظر است .
خط 11 متد Program_greatNumber را به نمونه جدیدی از Delegate ایجاد شده متصل میکند.
خط 12 مقداری از ورودی گرفته میشود.
در سطر 13 کنترل میشود که آیا مقدار ورودی بزرگتر از 100 میباشد یا خیر و همچنین کنترل متغیر رویداد greateNumber برای نداشتن مقدار تهی
سطر 15:در صورت برقرار بودن شرط نمونه ای از کلاس نگه داری کننده داده های رویداد با آرگومان مقدار وارد شده ایجاد میشود

سطر 16:رویداد اتفاق می افتد آرگومان اول نمونه ای از کلاسی است که رویداد در آن اتفاق افتاده است(Program) و آرگومان دوم اطلاعات مورد نیاز را برای این نمونه از این رویداد در خود دارد.

mohammad272005
جمعه 05 مرداد 1386, 04:58 صبح
دوست من با عرض تشکر بابت مقاله سودمندت باید یه مطلب کوچولو هم بهش اضافه کنم. اونم اینه که با generic کار از اینم ساده‏تر میشه:

classMyEventEventArgs : EventArgs
{
privateint _Test;
publicint Test
{
get { return _Test; }
privateset { _Test = value; }
}
public MyEventEventArgs(int test)
{
this.Test = test;
}
}
classEventTest
{
publiceventEventHandler<MyEventEventArgs> MyEvent;
publicvoid RaiseMyEvent(int test)
{
if (MyEvent != null) MyEvent(this, newMyEventEventArgs(test));
}
}
classProgram
{
staticvoid Main(string[] args)
{
EventTest eventTest = newEventTest();
eventTest.MyEvent += newEventHandler<MyEventEventArgs>(eventTest_MyEvent);
eventTest.RaiseMyEvent(5);
}
staticvoid eventTest_MyEvent(object sender, MyEventEventArgs e)
{
Console.WriteLine(e.Test);
}
}

یعنی به این ترتیب شما از تعریف delegate بی‏نیاز میشی اگر از

EventHandler<> استفاده کنی.

اَرژنگ
جمعه 05 مرداد 1386, 13:20 عصر
3)و کلاسی که رویداد را بالا می کشد(Raise می کند)

فکر کنم به جایه Raise
منظورتان Consume باشه؟
اگر که نه یک رفرانس به مقاله زبان اصلی بدید.
مرسی برایه زحمتتان.

Sajjad1364
شنبه 06 مرداد 1386, 15:59 عصر
با سلام
من این مقاله رو در MSDN دیدم که مربوط میشه به چند سال پیش و دقیقا آدرش یادم نیست.
به همین دلیل از ژنریک ها در این مقاله خبری نبود