Здравствуйте! Записался на ваш курс, но не понимаю как произвести оплату. Надо ли писать заявление и, если да, то куда отправлять? как я получу диплом о профессиональной переподготовке? |
Классы с событиями
Классы с большим числом событий
Как было сказано, каждое событие класса представляется полем этого класса. Если у класса много объявленных событий, а реально возникает лишь малая часть из них, то предпочтительнее динамический подход, когда память отводится только событиям, для которых есть связанные с ними обработчики события. Это несколько замедляет время выполнения, но экономит память. Решение зависит от того, что в данном контексте важнее - память или время. Для реализации динамического подхода в момент объявления события в языке предусмотрена возможность задания пользовательских методов Add и Remove. Это и есть другая форма объявления события, упоминавшаяся ранее. Вот ее примерный синтаксис:
public event <Имя Делегата> <Имя события> { add {…} remove {…} }
Оба метода должны быть реализованы, при этом для хранения делегатов используется некоторое хранилище. Именно так реализованы классы для большинства интерфейсных объектов, использующие хэш-таблицы для хранения делегатов.
Давайте построим небольшой пример, демонстрирующий такой способ объявления и работы с событиями. Вначале построим класс с несколькими событиями:
class ManyEvents { //хэш-таблица для хранения делегатов Hashtable DStore = new Hashtable(); public event EventHandler Ev1 { add {DStore["Ev1"]= (EventHandler)DStore["Ev1"]+ value;} remove {DStore["Ev1"]= (EventHandler)DStore["Ev1"]- value;} } //Аналогично объявляются события Ev2, Ev3, Ev4 public void SimulateEvs() { EventHandler ev = (EventHandler) DStore["Ev1"]; if(ev != null) ev(this, null); ev = (EventHandler) DStore["Ev3"]; if(ev != null) ev(this, null); } }//class ManyEvents
В нашем классе созданы четыре события и хэш-таблица DStore для их хранения. Все события принадлежат встроенному классу EventHandler. Когда к событию будет присоединяться обработчик, автоматически будет вызван метод add, который динамически создаст элемент хэш-таблицы, Ключом элемента в данном случае является строка с именем события. При отсоединении обработчика будет исполняться метод remove, выполняющий аналогичную операцию над соответствующим элементом хэш-таблицы. В классе определен также метод SimulateEvs, при вызове которого зажигаются два из четырех событий - Ev1 и Ev3.
Рассмотрим теперь класс Receiver3, который слушает события, приходящие от объектов класса ManyEvents. Этот класс построен по описанным ранее правилам. В нем есть четыре обработчика события и метод OnConnect, связывающий обработчиков с событиями. Вот код класса:
class Receiver3 { string name; public Receiver3(string name) { this.name = name; } public string Name { get { return name; } } public void OnConnect(ManyEvents me, int number) { switch (number) { case 1: { me.Ev1 += new EventHandler(H1); break; } case 2: { me.Ev2 += new EventHandler(H2); break; } case 3: { me.Ev3 += new EventHandler(H3); break; } case 4: { me.Ev4 += new EventHandler(H4); break; } } } public void H1(object s, EventArgs e) { Console.WriteLine("Слушатель " + name + " : Событие Ev1"); } public void H2(object s, EventArgs e) { Console.WriteLine("Слушатель " + name + " : Событие Ev2"); } public void H3(object s, EventArgs e) { Console.WriteLine("Слушатель " + name + " : Событие Ev3"); } public void H4(object s, EventArgs e) { Console.WriteLine("Слушатель " + name + " : Событие Ev4"); } }
Методу OnConnect передается объект класса ManyEvents и номер события, которое следует слушать. При выполнении этого метода происходит связывание события с его обработчиком и, как следствие, динамическое создание события и заполнение соответствующей строки хэш-таблицы объекта.
В тестирующей процедуре создаются один объект класса ManyEvents и два объекта класса Receiver3.
public void TestEvents() { ManyEvents me = new ManyEvents(); Receiver3 rev1 = new Receiver3("First"); rev1.OnConnect(me, 1); rev1.OnConnect(me, 3); Receiver3 rev2 = new Receiver3("Second"); rev2.OnConnect(me, 2); rev2.OnConnect(me, 3); me.SimulateEvs(); }
Объект rev1 слушает первое и третье события, приходящие от объекта me. Объект rev2 слушает второе и третье события, приходящие от объекта me. Метод Simulate зажигает первое и третье события. Слушатели сообщений получают уведомления о возникших событиях и реагируют должным образом. Результаты работы показаны на рис. 7.4.