Jan 6, 2014

მოვლენები (1/3) - მოვლენის განმსაზღვრელი


მოვლენები მთლიანად დაფუძნებულები არიან დელეგატებზე და რახან მოვრჩი დელეგატების განხილვას, ლოგიკური იქნება თუ ჩემი პოსტების გაგრძელება შეეხება ისეთ ელემენტებს, როგორიცაა მოვლენები. მოვლენები გვთავაზობს publish/subscribe მექანიზმს. ყველაფრის გადათარგმნა არ იქნება მოხერხებული და ამიტომ, ჩემი აზრით, სჯობს რამდენიმე ტერმინოლოგია ასე დავტოვო. მაგალითისათვის, რომ ავიღოთ Windows Forms ში Button კონტროლს აქვს Click მოვლენა. მოვლენის ეს ტიპი არის დელეგატი, ხოლო მომგვარებელი (handler) მეთოდის გამოძახება ხდება მაშინ, როდესაც აქტიურდება Click მოვლენა. მომგვარებელი ანუ მოპასუხე მეთოდის განსაზღვრა ხდება მომხმარებლის მიერ უმეტეს შემთხვევაში.

ჩემი აზრით მხოლოდ თეორიას ჯობს მაგალითებიც შევურიო მასში და ასეც მოვიქცევი. შევქმნი ახალ კლასს - JobDealer.cs, რომელიც სთავაზობს „მომხმარებელს“ მოვლენებზე დაფუძნებულ „გამოწერას“. JobDealer.cs განსაზღვრავს ახალ მოვლენას NewJobInfo, რომლის ტიპია EventHandler<JobInfoEventArgs> event საკვანძო სიტყვის გამოყენებით. NewJob() მეთოდის შიგნით ხდება NewJobInfo მოვლენის გააქტიურება.

public class JobInfoEventArgs : EventArgs
        {
            public JobInfoEventArgs(string job)
            {
                this.Job = job;
            }

            public string Job { get; private set; }
        }

        public class JobDealer
        {
            public event EventHandler<JobInfoEventArgs> NewJobInfo;

            public void NewJob(string job)
            {
                Console.WriteLine("JobDealer, new job {0}", job);
                if(NewJobInfo != null)
                {
                    NewJobInfo(this, new JobInfoEventArgs(job));
                }
            }
        }

JobDealer.cs კლასი მომხმარებელს სთავაზობს ახალ მოვლენას NewJobInfo რომლის ტიპია <JobInfoEventArgs>. კონვენციის თანახმად მოვლენები იყენებენ მეთოდებს, რომლებსაც გააჩნიათ ორი პარამეტრი. Sender ობიექტი, რომელიც ააქტიურებს მოვლენას და მეორე პარამეტრი აგზავნის მოვლენის შესახებ დამატებით ინფორმაციას. მეორე პარამეტრი სხვადასხვაა სხვადასხვა ტიპის მოვლენებისათვის. .NET 1.0 ში უკვე რამდენიმე ასეული დელეგატი იყო განსაზღვრული სხვადასხვა ტიპის მოვლენებისათვის. EventHandler<TEventArgs> განსაზღვრავს handlerს რომელიც აბრუნებს void ს და იღებს ორ არგუმენტს. EventHandler<TEventArgs> ის პირველი პარამეტრი უნდა იყოს object ტიპის, ხოლო მეორე პარამეტრის ტიპი არის T. EventHandler<TEventArgs> ასევე განსაზღვრავს T ტიპზე შეზღუდვას, რაც იმას ნიშნავს, რომ მიუხედავად იმისა, რომ T ტიპში ნებისმიერი ტიპი შეიძლება იგულისხმებოდეს, მაინც არსებობს გამონაკლისები და ყველა ტიპი არ შეიძლება ჩაჯდეს <> ფრჩხილებში. ეს შეზღუდვა კი მდებარეობს შემდეგში: T ს მაგივრად გამოყენებული კლასი აუცილებელია, რომ იყოს EventArgs ის მემკვიდრე. სწორედ ამიტომ არის გამოყენებული ჩემს მიერ შემოთავაზებულ მაგალითში განსაზღვრული კლასისთვის წინაპარი EventArgs კლასი.

public delegate void EventHandler<TEventArgs> (object sender, TEventArgs e)
                where TEventArgs : EventArgs

კლასი JobDealer.cs ააქტიურებს მოვლენას NewJob მეთოდში. NewJobInfo ს () ით გამოყენებით, იძახებთ ყველა იმ handler ს რომელსაც „გამოწერილი“ აქვს მოვლენა. Multicast დელეგატების მსგავსად handler ების გამოძახების თანმიმდევრობა არ არის დაცული, ამიტომ ესეც უნდა გაითვალისწინოთ თქვენს მიერ დაწერილ კოდში, რადგან ერთხელ შეიძლება იმუშაოს ყველაფერმა, ხოლო მეორეჯერ კი რაიმე შეცდომა ამოაგდოს და თავის ტკივილი გაგიჩინოთ.
ასევე ყურადღებაა იმ ფაქტზე გასამახვილებელი, რომ აუცილებლად უნდა შემოწმდეს NewJobInfo დელეგატის არსებობა, რადგან თუ ის არავის არ აქვს გამოწერილი მაშინ null ის ტოლია.

public void NewJob(string job)
            {
                Console.WriteLine("JobDealer, new job {0}", job);
                if(NewJobInfo != null)
                {
                    NewJobInfo(this, new JobInfoEventArgs(job));
                }

            }

No comments:

Post a Comment