Новые средства языка. Индексаторы. Делегат на основе обычного метода класса. Делегаты на основе класса MulticastDelegate, страница 9

Объект, породивший событие, называется отправителем (event sender), а объект, получивший его — получателем (event receiver). Важным моментом в этой модели является то, что отправитель не знает получателей. Событие просто публикуется (published), а получатели, которые на него подписаны (subscribed), получают его.

Функции проводника сообщения от отправителя к получателю выполняет делегат. Мы уже отмечали, что механизм событий основан на делегатной модели. Делегат соединяет событие с функцией его обработки. Схема обработки сообщения о событии сходна со схемой выбора делегата, которую мы рассмотрели ранее. Для того, чтобы отреагировать на событие, мы должны подписаться на получение сообщения о нем, добавив в список делегатов, поддерживаемый событием, своего делегата.

Преимущество модели: PublisherSubscriber состоит в том, что любое количество независимых классов может пописаться на получение уведомлений о событии. Подписчики ничего не знают о том, как работает Генератор событий (или Observer — наблюдатель за ними). В то же время и Publisher не должен знать, кто подписан на событие и как они реагируют на него.

Например, если кнопка возбуждает событие Click, то на него могут подписаться и реагировать произвольное количество независимых классов, объекты которых будут получать уведомления о событии и запускать цепочку делегатов. Последние выполняют множество заданий (каждый имеет свое собственное).

Делегаты играют роль посредников между генераторами событий и приемниками — объектами, подписанными на них. Источник, или генератор событий может изменить способ создания событий, например генерировать их реже или чаще, но это не разрушит модели взаимосвязей. Приемник также волен изменять способ реагирования на уведомления о событиях и это не повлияет на Источник.

Простой пример

Начнем с простого примера. Предположим, что наше приложение должно реагировать на сообщение о том, что пользователь изменил дату или время (date/time properties), поддерживаемые системой. Для этого в функцию Main мы можем поместить такое объявление:

SystemEvents.TimeChanged += new EventHandler (MyTimeHandler);

Оно добавляет в список заданий события TimeChanged, которое определено в классе SystemEvents из пространства имен Microsoft.Win32, адрес еще одной функции, которую оно должно вызвать. Класс SystemEvents содержит несколько других объектов типа event, которые оповещают о глобальных системных событиях все подписавшиеся на них объекты. Сам класс описан как:

public sealed class SystemEvents;

Событие — это специальный объект, который удобно представлять себе в виде списка делегатов, выполняющих свои списки заданий в случае наступления события. EventHandler — это делегат, который соединяет событие с функцией его обработки. Он объявлен как:

public delegate void EventHandler(object sender, EventArgs e)

и имеет функциональность самого простого делегата, не несущего с собой данные о событии. Его используют для обработки произвольных событий общего характера.

Функцию MyTimeHandler, как вы догадались, надо вставить в класс нашего приложения. Здесь придется решать, в какой класс лучше вставить новый статический метод MyTimeHandler. Введем его в класс Test. Причиной такого выбора может служить то, что другие классы логически не связаны с нашими намерениями опробовать механизм событий. По договоренности делегаты событий (event delegates) в среде .NET Framework имеют два параметра: источник, возбудивший событие и данные о событии. Поэтому можно считать, что сигнатура функции обработки события уже определена делегатом и должна иметь вид:

public static void MyTimeHandler(object sender, EventArgs e)

{

Console.WriteLine("\n\nSystem time changed:  " + e);

}