Вход/Регистрация
Полное руководство. С# 4.0
вернуться

Шилдт Герберт

Шрифт:

В приведенной ниже программе создается класс X, в котором метод экземпляра определяется в качестве обработчика событий. Это означает, что каждый объект класса X должен быть зарегистрирован отдельно, чтобы получать уведомления о событиях. Для демонстрации этого факта в данной программе производится групповая адреса ция события трем отдельным объектам класса X. /* Уведомления о событиях получают отдельные объекты, когда метод экземпляра используется в качестве обработчика событий. */ using System; // Объявить тип делегата для события. delegate void MyEventHandler; // Объявить класс, содержащий событие. class MyEvent { public event MyEventHandler SomeEvent; // Этот метод вызывается для запуска события. public void OnSomeEvent { if(SomeEvent != null) SomeEvent; } } class X { int id; public X(int x) { id = x; } // Этот метод экземпляра предназначен в качестве обработчика событий. public void Xhandler { Console.WriteLine("Событие получено объектом " + id); } } class EventDemo3 { static void Main { MyEvent evt = new MyEvent; X o1 = new X(1); X o2 = new X(2); X o3 = new X(3); evt.SomeEvent += o1.Xhandler; evt.SomeEvent += o2.Xhandler; evt.SomeEvent += o3.Xhandler; // Запустить событие. evt.OnSomeEvent; } }

Выполнение кода из этого примера приводит к следующему результату. Событие получено объектом 1 Событие получено объектом 2 Событие получено объектом 3

Как следует из результата выполнения кода из приведенного выше примера, каж дый объект должен зарегистрировать свой интерес в событии отдельно, и тогда он бу дет получать отдельное уведомление о событии.

С другой стороны, когда в качестве обработчика событий используется статический метод, события обрабатываются независимо от какого-либо объекта, как демонстриру ется в приведенном ниже примере программы. /* Уведомления о событии получает класс, когда статический метод используется в качестве обработчика событий. */ using System; // Объявить тип делегата для события. delegate void MyEventHandler; // Объявить класс, содержащий событие. class MyEvent { public event MyEventHandler SomeEvent; // Этот метод вызывается для запуска события. public void OnSomeEvent { if(SomeEvent != null) SomeEvent; } } class X { /* Этот статический метод предназначен в качестве обработчика событий. */ public static void Xhandler { Console.WriteLine("Событие получено классом."); } } class EventDemo4 { static void Main { MyEvent evt = new MyEvent; evt.SomeEvent += X.Xhandler; // Запустить событие. evt.OnSomeEvent; } }

При выполнение кода этого примера получается следующий результат. Событие получено классом.

Обратите в данном примере внимание на то, что объекты класса X вообще не создаются. Но поскольку Xhandler является статическим методом класса X, то он может быть привязан к событию SomeEvent и выполнен при вызове метода OnSomeEvent. Применение аксессоров событий

В приведенных выше примерах события формировались в форме, допускавшей ав томатическое управление списком вызовов обработчиков событий, включая добавле ние и удаление обработчиков событий из списка. Поэтому управление этим списком не нужно было организовывать вручную. Благодаря именно этому свойству такие со бытия используются чаще всего. Тем не менее организовать управление списком вы зовов обработчиков событий можно и вручную, чтобы, например, реализовать специ альный механизм сохранения событий.

Для управления списком обработчиков событий служит расширенная форма опе ратора event, позволяющая использовать аксессоры событий. Эти аксессоры предо ставляют средства для управления реализацией подобного списка в приведенной ниже форме. event делегат_события имя_события { add { // Код добавления события в цепочку событий. } remove { // Код удаления события из цепочки событий. } }

В эту форму входят два аксессора событий: add и remove. Аксессор add вызывается, когда обработчик событий добавляется в цепочку событий с помощью оператора +=. В то же время аксессор remove вызывается, когда обработчик событий удаляется из цепочки событий с помощью оператора -=.

Когда вызывается аксессор add или remove, он принимает в качестве параметра добавляемый или удаляемый обработчик. Как и в других разновидностях аксессоров, этот неявный параметр называется value. Реализовав аксессоры add или remove, можно организовать специальную схему хранения обработчиков событий. Например, обработчики событий можно хранить в массиве, стеке или очереди.

Ниже приведен пример программы, демонстрирующей аксессорную форму со бытия. В ней для хранения обработчиков событий используется массив. Этот массив состоит всего из трех элементов, поэтому в цепочке событий можно хранить одновре менно только три обработчика. // Создать специальные средства для управления списками // вызова обработчиков событий. using System; // Объявить тип делегата для события. delegate void MyEventHandler; // Объявить класс для хранения максимум трех событий. class MyEvent { MyEventHandler[] evnt = new MyEventHandler[3]; public event MyEventHandler SomeEvent { // Добавить событие в список. add { int i; for(i=0; i < 3; i++) if(evnt[i] == null) { evnt[i] = value; break; } if (i == 3) Console.WriteLine("Список событий заполнен."); } // Удалить событие из списка. remove { int i; for(i=0; i < 3; i++) if(evnt[i] == value) { evnt[i] = null; break; } if (i == 3) Console.WriteLine("Обработчик событий не найден."); } } // Этот метод вызывается для запуска событий. public void OnSomeEvent { for(int i=0; i < 3; i++) if(evnt[i] != null) evnt[i]; } } // Создать ряд классов, использующих делегат MyEventHandler. class W { public void Whandler { Console.WriteLine("Событие получено объектом W"); } } class X { public void Xhandler { Console.WriteLine("Событие получено объектом X"); } } class Y { public void Yhandler { Console.WriteLine("Событие получено объектом Y"); } } class Z { public void Zhandler { Console.WriteLine("Событие получено объектом Z"); } } class EventDemo5 { static void Main { MyEvent evt = new MyEvent; W wOb = new W; X xOb = new X; Y yOb = new Y; Z zOb = new Z; // Добавить обработчики в цепочку событий. Console.WriteLine("Добавление событий. "); evt.SomeEvent += wOb.Whandler; evt.SomeEvent += xOb.Xhandler; evt.SomeEvent += yOb.Yhandler; // Сохранить нельзя - список заполнен. evt.SomeEvent += zOb.Zhandler; Console.WriteLine; // Запустить события. evt.OnSomeEvent; Console.WriteLine; // Удалить обработчик. Console.WriteLine("Удаление обработчика xOb.Xhandler."); evt.SomeEvent -= xOb.Xhandler; evt.OnSomeEvent; Console.WriteLine; // Попробовать удалить обработчик еще раз. Console.WriteLine("Попытка удалить обработчик " + "xOb.Xhandler еще раз."); evt.SomeEvent -= xOb.Xhandler; evt.OnSomeEvent; Console.WriteLine; // А теперь добавить обработчик Zhandler. Console.WriteLine("Добавление обработчика zOb.Zhandler."); evt.SomeEvent += zOb.Zhandler; evt.OnSomeEvent; } }

Ниже приведен результат выполнения этой программы: Добавление событий. Список событий заполнен. Событие получено объектом W Событие получено объектом X Событие получено объектом Y Удаление обработчика xOb.Xhandler. Событие получено объектом W Событие получено объектом Y Попытка удалить обработчик xOb.Xhandler еще раз. Обработчик событий не найден. Событие получено объектом W Событие получено объектом Y Добавление обработчика zOb.Zhandler. Событие получено объектом W Событие получено объектом X Событие получено объектом Y

Рассмотрим данную программу более подробно. Сначала в ней определяется деле гат обработчиков событий MyEventHandler. Затем объявляется класс MyEvent. В са мом его начале определяется массив обработчиков событий evnt, состоящий из трех элементов. MyEventHandler[] evnt = new MyEventHandler[3];

Этот массив служит для хранения обработчиков событий, добавляемых в цепочку событий. По умолчанию элементы массива evnt инициализируются пустым значе нием (null).

Далее объявляется событие SomeEvent. В этом объявлении используется приведен ная ниже аксессорная форма оператора event. public event MyEventHandler SomeEvent { // Добавить событие в список. add { int i; for(i=0; i < 3; i++) if(evnt[i] == null) { evnt[i] = value; break; } if (i == 3) Console.WriteLine("Список событий заполнен."); } // Удалить событие из списка. remove { int i; for(i=0; i < 3; i++) if(evnt[i] == value) { evnt[i] = null; break; } if (i == 3) Console.WriteLine("Обработчик событий не найден."); } }

Когда в цепочку событий добавляется обработчик событий, вызывается аксессор add, и в первом неиспользуемом (т.е. пустом) элементе массива evnt запоминается ссылка на этот обработчик, содержащаяся в неявно задаваемом параметре value. Если в массиве отсутствуют свободные элементы, то выдается сообщение об ошибке. (Разу меется, в реальном коде при переполнении списка лучше сгенерировать соответствую щее исключение.) Массив evnt состоит всего из трех элементов, поэтому в нем можно сохранить только три обработчика событий. Когда же обработчик событий удаляется из цепочки событий, то вызывается аксессор remove и в массиве evnt осуществляется поиск ссылки на этот обработчик, передаваемой в качестве параметра value. Если ссылка найдена, то соответствующему элементу массива присваивается пустое значе ние (null), а значит, обработчик удаляется из цепочки событий.

  • Читать дальше
  • 1
  • ...
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: