Опубликован: 02.12.2009 | Уровень: специалист | Доступ: платный | ВУЗ: Тверской государственный университет
Лекция 8:

Классы с событиями

< Лекция 7 || Лекция 8: 12345 || Лекция 9 >

Классы с большим числом событий

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

Объекты с множественными событиями

Рис. 7.4. Объекты с множественными событиями
< Лекция 7 || Лекция 8: 12345 || Лекция 9 >
Федор Антонов
Федор Антонов

Здравствуйте!

Записался на ваш курс, но не понимаю как произвести оплату.

Надо ли писать заявление и, если да, то куда отправлять?

как я получу диплом о профессиональной переподготовке?

Илья Ардов
Илья Ардов

Добрый день!

Я записан на программу. Куда высылать договор и диплом?

Дмитрий Штаф
Дмитрий Штаф
Россия
Дмитрий Слапогузов
Дмитрий Слапогузов
Россия, Бийск