"Разборчивые" события

We use cookies. Read the Privacy and Cookie Policy

"Разборчивые" события

Есть еще одно усовершенствование, которое можно внести в наш пример с CarEvents и которое соответствует шаблону событий, рекомендуемому разработчиками из Microsoft. При исследовании событий, посылаемых данным типом из библиотек базовых классов, вы обнаружите, что первым параметром соответствующего делегата является System.Object, а вторым – тип, производный от System.EventArgs.

Аргумент System.Object представляет ссылку на объект, посылающий событие (такой как, например, Car), а второй параметр представляет информацию о соответствующем событии. Базовый класс System.EventArgs представляет событие и не передает никакой пользовательской информации.

public class EventArgs {

 public static readonly System.EventArgs Empty;

 public EventArgs();

}

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

public class CarEventArgs: EventArgs {

 public readonly string msg;

 public CarEventArgs(string message) {

  msg = message;

 }

}

Теперь мы должны обновить делегат CarEventHandler так, как показано ниже (события должны остаться без изменений).

public class Car {

 public delegate void CarEventHandler(object sender, CarEventArgs e);

 …

}

При генерировании событий из метода Accelerate() мы теперь должны предоставить ссылку на текущий объект Car (с помощью ключевого слова Car) и экземпляр нашего типа CarEventArgs.

public void Accelerate(int delta) {

 // Если машина сломалась, генерируется событие Exploded.

 if (carIsDead) {

  if (Exploded != null) Exploded(this, new CarEventArgs("Извините, машина сломалась…"));

  else {

   …

   AboutToBlow(this, new CarEventArgs("Осторожно! Могу сломаться!"));

  }

  …

 }

}

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

public static void CarAboutToBlow(object sender, CarEventArgs e) { Console.WriteLine ("{0} сообщает: {1}", sender, e.msg); }

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

public static void CarIsAlmostDoomed(object sender, CarEventArgs e) {

 // Просто для гарантии здесь перед вызовом предлагается

 // проверка среды выполнения.

 if (sender is Car) {

  Car с = (Car)sender;

  c.CrankTunes(false);

 }

 Console.WriteLine("Важное сообщение от {0}: {1}", sender, e.msg);

}

Исходный код. Проект PrimAndProperCarEvenfs размещен в подкаталоге, соответствующем главе 8.