|
Здравствуйте! Записался на ваш курс, но не понимаю как произвести оплату. Надо ли писать заявление и, если да, то куда отправлять? как я получу диплом о профессиональной переподготовке? |
Классы с событиями
Классы с большим числом событий
Как было сказано, каждое событие класса представляется полем этого класса. Если у класса много объявленных событий, а реально возникает лишь малая часть из них, то предпочтительнее динамический подход, когда память отводится только событиям, для которых есть связанные с ними обработчики события. Это несколько замедляет время выполнения, но экономит память. Решение зависит от того, что в данном контексте важнее - память или время. Для реализации динамического подхода в момент объявления события в языке предусмотрена возможность задания пользовательских методов 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.
