Интернет-журнал "Домашняя лаборатория", 2007 №9
Шрифт:
Итак, если событие имеет аргументы, то все входные аргументы должны быть закрыты для обработчиков события. Если обработчиков несколько, то лучше или не использовать выходных аргументов, или аккуратно запрограммировать логику обработчиков, которая учитывает решения, полученные коллегами — ранее отработавшими обработчиками события.
Классы с большим числом событий
Как было сказано, каждое событие класса представляется полем этого класса.
public event <Имя Делегата> <Имя события>
{
add {…}
remove {… }
}
Оба метода должны быть реализованы, при этом для хранения делегатов используется некоторое хранилище. Именно так реализованы классы для большинства интерфейсных объектов, использующие хэш-таблицы для хранения делегатов.
Давайте построим небольшой пример, демонстрирующий такой способ объявления и работы с событиями. Вначале построим класс с несколькими событиями:
class ManyEvents
{
//хэш таблица для хранения делегатов
Hashtable DStore = new Hashtable;
public event EventHandier Evl
{
add
{
DStore["Evl"]= (EventHandier)DStore["Evl"]+ value;
}
remove
{
DStore["Evl"]= (EventHandier)DStore["Evl"] - value;
}
}
public event EventHandier Ev2
{
add
{
DStore["Ev2"]= (EventHandier)DStore["Ev2"]+ value;
}
remove
{
DStore["Ev2"]= (EventHandier)DStore["Ev2"] - value;
}
}
public event EventHandier Ev3
{
add
{
DStore["Ev3"]= (EventHandier)DStore["Ev3"]+ value;
}
remove
{
DStore["Ev3"]= (EventHandier)DStore["Ev3"] - value;
}
}
public event EventHandier Ev4
{
add
{
DStore["Ev4"]= (EventHandler)DStore["Ev4"] - value;
}
remove
}
DStore["Ev4"]= (EventHandler)DStore["Ev4"] - value;
}
}
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, который динамически создаст элемент хэш-таблиц. Ключом элемента является, в данном случае, строка с именем события. При отсоединении обработчика будет исполняться
Рассмотрим теперь класс ReceiverEvs, слушающий события. Этот класс построен по описанным ранее правилам. В нем есть ссылка на класс, создающий события; конструктор с параметром, которому передается реальный объект такого класса; четыре обработчика события — по одному на каждое, и метод OnConnect, связывающий обработчиков с событиями. Вот код класса:
class ReceiverEvs
{
private ManyEvents manyEvs;
public ReceiverEvs(ManyEvents manyEvs)
{
this.manyEvs = manyEvs;
OnConnect ;
}
public void OnConnect
{
manyEvs.Ev1 += new EventHandler(H1);
manyEvs.Ev2 += new EventHandler(H2);
manyEvs.Ev3 += new EventHandler (H3);
manyEvs.Ev4 += new EventHandler(H4);
}
public void HI (object s, EventArgs e)
{
Console.WriteLine("Событие Ev1");
}
public void H2 (object s, EventArgs e)
{
Console.WriteLine("Событие Ev2");
}
public void H3 (object s, EventArgs e)
{
Console.WriteLine("Событие Ev3");
}
public void H4 (object s, EventArgs e)
{
Console.WriteLine("Событие Ev4");
}
}//class ReceiverEvs
Тестирующая процедура состоит из нескольких строчек, в которых создаются нужные объекты и запускается метод Simulate, зажигающий события:
public void TestManyEvents
{
ManyEvents me = new ManyEvents ;
ReceiverEvs revs = new ReceiverEvs(me);
me.SimulateEvs;
}
Все работает предусмотренным образом.
Проект "Город и его службы"
Завершить лекцию о событиях хочется содержательным учебным проектом, в котором моделируется жизнь города, происходящие в нем события и реакция на них городских служб. Наша главная цель в данном проекте — еще раз показать, как возникающее событие, в данном случае — пожар в одном из домов города, обрабатывается по-разному городскими службами — пожарными, милицией, скорой помощью. Конечно, все упрощено, в реальном городе событиями являются не только пожары и преступления, но и более приятные ситуации: день города, открытие фестивалей и выставок, строительство новых театров и институтов.
Начнем с описания класса, задающего наш город. Этот класс уже появлялся и в этой, и в предыдущей лекции, здесь его описание будет расширено. Начнем со свойств класса:
public class NewTown
{
//свойства
private int build, BuildingNumber; //дом и число домов в городе
private int day, days; //Текущий день года
//городские службы
private Police policeman;
private Ambulance ambulanceman;
private FireDetect fireman;
//события в городе