Основы, лучшие методы и соглашения реализации событий в C# - Реализация типового события и обработка событий, вызванных компонентами среды разработки .NET

ОГЛАВЛЕНИЕ

13. Реализация типового события

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

Это типовое событие возбуждается, когда файл перемещается утилитой для перемещения файлов (в примере проекта). Данные события содержат (1) имя перемещенного файла, (2) путь к исходной папке, и (3) путь к файлу назначения.

13.1 Код публикатора типового события

Шаг 1: Производный класс от EventArgs

Здесь мы порождаем новый класс, MoveFileEventArgs, от EventArgs, чтобы инкапсулировать данные события, отправляемые подписчику.

public class MoveFileEventArgs : EventArgs
{
   // Поля
   private string m_FileName = string.Empty;
   private string m_SourceFolder = string.Empty;
   private string m_DestinationFolder = string.Empty;

   // Конструктор
   public MoveFileEventArgs(string fileName, string sourceFolder,
      string destinationFolder)
   {
      m_FileName = fileName;
      m_SourceFolder = sourceFolder;
      m_DestinationFolder = destinationFolder;
   }
   // Свойства (неизменяемые)
   public string FileName
   {
      get { return m_FileName; }
   }

   public string SourceFolder
   {
      get { return m_SourceFolder; }
   }

   public string DestinationFolder
   {
      get { return m_DestinationFolder; }
   }
}

Шаг 2: Обработчик события (делегат)

Здесь мы объявляем новый делегат, соответствующий соглашениям события, возвращающий void и принимающий два параметра; object, имеющий имя 'sender', и EventArgs, имеющий имя 'e'.

public delegate void MoveFileEventHandler(object sender, 
    MoveFileEventArgs e);

Шаг 3: Объявление события

Здесь мы объявляем событие с использованием полеподобного синтаксиса.

public event MoveFileEventHandler MoveFile;

Шаг 4: Метод, возбуждающий событие

Здесь мы объявляем метод, возбуждающий событие.

private void OnMoveFile()
{
   if (MoveFile != null) // будет пустым, если нет подписчиков
   {
      MoveFile(this, new MoveFileEventArgs("SomeFileName.txt",
          @"C:\TempSource", @"C:\TempDestination"));
   }
}

Шаг 5: Возбуждение события

У нас есть метод, выполняющий нужную работу (перемещающий файл). Сразу после завершения работы вызывается метод, возбуждающий событие.

public void UserInitiatesFileMove()
{
   // код здесь перемещает файл.

   // после этого мы вызываем метод, возбуждающий событие MoveFile
   OnMoveFile();
}

13.2 Код подписчика типового события

Шаг 1: Написание метода обработки события

Этот метод вызывается, когда экземпляр fileMover возбуждает событие MoveFile. Его сигнатура точно совпадает с сигнатурой обработчика события.

void fileMover_MoveFile(object sender, MoveFileEventArgs e) 
{
   MessageBox.Show(sender.ToString() + " moved the file, " +
      e.FileName + ", from " +
      e.SourceFolder + " to " +  e.DestinationFolder);
}

Шаг 2: Создание экземпляра публикатора события

FileMover fileMover = new FileMover();

Шаг 3: Создание экземпляра обработчика события вместе с регистрацией подписчика (метода обработки события) в событии

Этот подход объединяет шаги 3 и 4 из шагов, перечисленных в разделе 14.2.

fileMover.MoveFile += new FileMover.MoveFileEventHandler(
    fileMover_MoveFile);

14. Обработка событий, вызванных компонентами среды разработки .NET – пошаговый разбор и пример

Соглашения по реализации событий, описанные в данной статье, можно обнаружить во всех реализациях событий, принадлежащих среде разработки .NET. Цель данного пошагового руководства – показать, как один компонент среды разработки .NET предоставляет свои события, и как можно написать код, запускающийся при возбуждении события. Вы поймете, что требуемые шаги – подгруппа рекомендуемых шагов, требуемых для реализации ваших собственных событий и методов обработки событий.

Этот раздел показывает, как среда разработки использует эти соглашения  путем пошагового разбора реализации события Deleted(удалено) компонента FileSystemWatcher(«сторож файловой системы»). FileSystemWatcher – класс, предоставляемый в пространстве имен System.IO среды разработки .NET. Этот класс может использоваться для уведомления вашего приложения, когда конкретное место ввода/вывода на диск совершается в конкретной папке (например, создан новый файл, файл изменен или удален, и т.д.).

14.1 Реализация события 'Deleted' FileSystemWatcher

Класс System.IO.FileSystemWatcher предоставляет событие Deleted , которое возбуждается экземпляром FileSystemWatcher, когда он обнаруживает, что файл был удален в папке, за которой он следит.

Объявление события

Так класс FileSystemWatcher среды разработки .NET объявляет свое событие Deleted:

public event FileSystemEventHandler Deleted

Объявление делегата

Используется делегат FileSystemEventHandler, объявленный в среде разработки .NET так:

public delegate void FileSystemEventHandler (Object sender, 
   FileSystemEventArgs e)

Заметьте, что делегат FileSystemEventHandler соответствует соглашению принятия двух параметров – первый, именуемый sender, имеет тип System.Object, и второй параметр, именуемый 'e', имеет тип System.EventArgs или тип его потомка. В этом случае заданный FileSystemEventArgs является потомком (как описано ниже).

Пользовательские EventArgs

Событие Deleted передает информацию об удаленном файле или каталоге с помощью подкласса System.EventArgs:

public class FileSystemEventArgs : EventArgs {}

Класс FileSystemEventArgs расширяет System.EventArgs путем добавления следующих свойств:
•    ChangedType - Получает тип произошедшего изменения каталога (передается как значение перечисления WatcherChangeType - создан, удален, изменен, и т.д.)
•    FullPath – Получает полный путь к измененному файлу или каталогу
•    Name – Получает имя измененного файла или каталога

Когда событие Deleted возбуждается, экземпляр FileSystemWatcher отправляет путь, имя файла и т.д. подписчикам события. Это значит, что каждый подписчик не только узнает, что файл был удален, но и какой именно файл был удален.

Отметьте, что имя обработчика события, FileSystemEventHandler, не полностью соответствует соглашению об именовании, говорящему, что именем обработчика события должно быть имя события, за которым следует слово Handler. Помните, что соглашения – не законы или правила. Наоборот, они являются советами, как сделать ваш код более понятным. В случае класса FileSystemWatcher один обработчик события был реализован для поддержки нескольких событий, включая Deleted, Created и Changed – отсюда и незначительное нарушение строгой интерпретации соглашения об именовании. Строгое следование соглашению привело бы к созданию 3 одинаковых делегатов с разными именами (например, DeletedHandler, CreatedHandler, и т.д.). Или же можно было выбрать имя вроде такого DeletedOrCreatedOrChangedHandler, что было бы нелепо. В данном случае было выбрано разумное отступление от соглашения.

14.2 Обработка события FileSystemWatcher.Deleted

С учетом вышеуказанной реализации события, предоставленной средой разработки .NET, ниже приведен пример кода, который вы могли бы написать в вашем классе, который подписался бы на событие Deleted экземпляра FileSystemWatcher.

Этот код позволил бы вашему приложению реагировать на удаляемые файлы в каталоге C:\Temp.

// Импорт пространства имен
using System.IO;

// Объявление переменной fsWatcher – вероятно, на уровне класса.
FileSystemWatcher fsWatcher = new FileSystemWatcher();

//Инициализация экземпляра – вероятно, в конструкторе или методе, вызванном из

constructor.
fsWatcher.Path = "C:\Temp";
fsWatcher.Deleted += new FileSystemEventHandler(fsWatcher_Deleted);

// это булево свойство включает или отключает возбуждение событий чем-то

FileSystemWatcher instance.
fsWatcher.EnableRaisingEvents = true;
// включите в случае обновления компонентов Windows Forms
fsWatcher.SynchronizingObject = this;

// метод обработки события
void fsWatcher_Deleted(object sender, FileSystemEventArgs e)
{
   MessageBox.Show(e.Name + " was deleted" );
}