English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
События являются уведомлениями, отправляемыми объектом, чтобы中表示操作的 выполнения. В .NET события следуют шаблону проектирования наблюдателя.
Класс, вызывающий событие, называется Publisher(публикатор), класс, который принимает уведомления, называется Subscriber(подписчик). Одно событие может иметь несколько подписчиков. Обычно, публикатор вызывает событие при выполнении определенного действия. Подписчики хотят получать уведомления при выполнении действия, они должны зарегистрироваться в событии и обработать его.
В C# события являются обернутыми делегатами. Они зависят от делегатов. Делегаты определяют подписчикам класса的事件 обработчиков методы подписки.
Ниже приведена иллюстрация событий в C#.
События объявляются и генерируются в классе и связаны с обработчиками событий через делегаты из того же класса или другого класса. Класс, содержащий события, используется для публикации событий. Это называется Publisher(publisher) класс. Другие классы, принимающие это событие, называются классами подписчиков(subscriber). События используются publish-subscribe(publisher-subscriber) модель.
Publisher(publisher)- Это объект, который содержит определения событий и делегатов. Связь между событиями и делегатами также определена в этом объекте. Объекты класса Publisher(publisher) вызывают это событие и информируют другие объекты.
Подписчик(subscriber)- это объект, который принимает событие и предоставляет обработчик события. В классе публикатора вызывается директива на метод класса подписчика (обработчик события).
Событие можно объявить в два шага:
Объявление директивы
Использование ключевого слова event для объявления переменной директивы
Следующий пример демонстрирует, как объявлять событие в классе публикатора.
public delegate void Notify(); // Директива public class ProcessBusinessLogic { public event Notify ProcessCompleted; // Событие }
В предыдущем примере мы объявили директиву Notify и в классе ProcessBusinessLogic использовали ключевое слово event для объявления события ProcessCompleted типа директивы Notify. Таким образом, класс ProcessBusinessLogic называется publisher (публикатор). Директива Notify определяет подпись обработчика события ProcessCompleted. Она определяет, что метод обработчика события в классе subscriber (подписчик) должен иметь тип возвращаемого значения void и не иметь параметров.
Теперь让我们看看如何 вызвать событие ProcessCompleted. Посмотрите на следующее выполнение.
public delegate void Notify(); // Директива public class ProcessBusinessLogic { public event Notify ProcessCompleted; // Событие public void StartProcess() { Console.WriteLine("Process Started!"); // некоторые коды здесь.. OnProcessCompleted(); } protected virtual void OnProcessCompleted() // Защищенный виртуальный метод { // Если ProcessCompleted не null, вызывается директива ProcessCompleted?.Invoke(); } }
Верх, метод StartProcess() вызывает метод onProcessCompleted() в конце, что вызывает событие. Обычно, чтобы вызвать событие, следует использовать защищенный и виртуальный метод с определенным именем <EventName>. Защищенный и виртуальный позволяют производным классам перезаписывать логику вызова события. Однако производные классы должны всегда вызывать метод On<ENAME> базового класса, чтобы обеспечить получение события зарегистрированными директивами.
Метод OnProcessCompleted() использует вызов ProcessCompleted?.invoke() для директивы.
Класс подписчика должен быть зарегистрирован в событие ProcessCompleted и использовать метод Notify с соответствующим署ним для обработки его, как показано ниже.
class Program { public static void Main() { ProcessBusinessLogic bl = new ProcessBusinessLogic(); bl.ProcessCompleted += bl_ProcessCompleted; // регистрация события bl.StartProcess(); } // обработчик событий public static void bl_ProcessCompleted() { Console.WriteLine("Process Completed!"); } }
В примере, Program класс является ProcessCompleted Подписчики на события. Он использует оператор + = для регистрации события. Помните, что это также аналогично добавлению метода в список вызовов multicast делегата. Метод bl_processcompleted () обрабатывает это событие, так как он соответствует сигнатуре делегата Notify.
.NET Framework содержит встроенные типы делегатов для наиболее распространенных событий: EventHandler и EventHandler<TEventArgs>. Обычно любое событие должно включать два параметра: источник события и данные события. Для всех событий, не содержащих данных, используется делегат EventHandler. Для событий, содержащих данные, которые нужно передать обработчику, используется делегат EventHandler<TEventArgs>.
В примере, который показан выше, можно использовать делегат EventHandler, не объявляя пользовательский делегат Notify, как показано ниже.
class Program { public static void Main() { ProcessBusinessLogic bl = new ProcessBusinessLogic(); bl.ProcessCompleted += bl_ProcessCompleted; // регистрация события bl.StartProcess(); } // обработка событий public static void bl_ProcessCompleted(object sender, EventArgs e) { Console.WriteLine("Process Completed!"); } } public class ProcessBusinessLogic { // использование встроенного EventHandler для объявления события public event EventHandler ProcessCompleted; public void StartProcess() { Console.WriteLine("Process Started!"); // некоторые коды здесь.. OnProcessCompleted(EventArgs.Empty); // без данных события } protected virtual void OnProcessCompleted(EventArgs e) { ProcessCompleted?.Invoke(this, e); } }
В предыдущем примере метод обработчика событий bl_ProcessCompleted() содержит два параметра, соответствующие делегату EventHandler. В то же время передается this в качестве отправителя и EventArgs. Когда мы вызываем событие с помощью Invoke() в методе OnProcessCompleted(), он является пустым. Поскольку наши события не требуют данных, они просто уведомляют подписчиков о завершении процесса, поэтому мы передаем EventArgs.Empty.
Большинство событий передают некоторые данные подписчикам. Класс EventArgs является базовым классом для всех классов данных событий. .NET содержит множество встроенных классов данных событий, таких как SerialDataReceivedEventArgs. Они следуют命名ному шаблону, заканчивающемуся EventArgs. Вы можете создать пользовательские классы данных событий, наследуя класс EventArgs.
Передайте данные в обработчик с использованием EventHandler<TEventArgs>, как показано ниже.
class Program { public static void Main() { ProcessBusinessLogic bl = new ProcessBusinessLogic(); bl.ProcessCompleted += bl_ProcessCompleted; // регистрация события bl.StartProcess(); } // обработка событий public static void bl_ProcessCompleted(object sender, bool IsSuccessful) { Console.WriteLine("Process " + (IsSuccessful ? "Completed Successfully" : "failed")); } } public class ProcessBusinessLogic { // использование встроенного EventHandler для объявления события public event EventHandler<bool> ProcessCompleted; public void StartProcess() { try { Console.WriteLine("Process Started!"); // некоторые коды здесь.. OnProcessCompleted(true); } catch(Exception ex) { OnProcessCompleted(false); } } protected virtual void OnProcessCompleted(bool IsSuccessful) { ProcessCompleted?.Invoke(this, IsSuccessful); } }
В примере выше мы передаем единичный булевый значение обработчику, чтобы указать, успешен ли процесс.
Если вы хотите передавать несколько значений в качестве данных события, вы можете создать класс, наследующийся от базового класса EventArgs, например.
class ProcessEventArgs : EventArgs { public bool IsSuccessful { get; set; } public DateTime CompletionTime { get; set; } }
Ниже приведен пример того, как передавать пользовательский класс ProcessEventArgs обработчику.
class Program { public static void Main() { ProcessBusinessLogic bl = new ProcessBusinessLogic(); bl.ProcessCompleted += bl_ProcessCompleted; // регистрация события bl.StartProcess(); } // обработка событий public static void bl_ProcessCompleted(object sender, ProcessEventArgs e) { Console.WriteLine("Process " + (e.IsSuccessful ? "Completed Successfully" : "failed")); Console.WriteLine("Completion Time: " + e.CompletionTime.ToLongDateString()); } } public class ProcessBusinessLogic { // использование встроенного EventHandler для объявления события public event EventHandler<ProcessEventArgs> ProcessCompleted; public void StartProcess() { var data = new ProcessEventArgs(); try { Console.WriteLine("Process Started!"); // некоторые коды здесь.. data.IsSuccessful = true; data.CompletionTime = DateTime.Now; OnProcessCompleted(data); } catch(Exception ex) { data.IsSuccessful = false; data.CompletionTime = DateTime.Now; OnProcessCompleted(data); } } protected virtual void OnProcessCompleted(ProcessEventArgs e) { ProcessCompleted?.Invoke(this, e); } }
Таким образом, вы можете создавать, инициировать, регистрировать и обрабатывать события в C#.
Событие является оберткой для делегата. Это зависит от делегата.
Используйте ключевое слово 'event' вместе с переменной типа делегата для объявления события.
внутренний делегатEventHandler илиEventHandler <TEventArgs> используется для общих событий.
Класс издателя вызывает событие, а класс подписчика регистрирует событие и предоставляет метод обработчика события.
Метод, вызываемый событием, должен называться по имени события и начинаться с префикса «On».
Подпись метода обработчика должна соответствовать подписи делегата.
Используйте оператор + = для регистрации событий. Используйте -= для отмены подписки, не используйте оператор =.
Используйте EventHandler <TEventArgs> для передачи данных события.
ПроизводитеEventArgs базового класса для создания пользовательских классов данных событий.
События могут быть объявлены как статические, виртуальные, герметичные и абстрактные (static, virtual, sealed, abstract).
Интерфейс может включать события в качестве членов.
Если есть несколько подписчиков, событие будет синхронно вызывать обработчик.