C# 事件
- 一、事件
- 二、事件的應用
- 三、事件的自定義聲明
一、事件
- 定義:“a thing that happens, especially something important” / “能夠發生的什么事情”
- 角色:使對象或類具備通知能力的成員
- 使用:用于對象或類間的動作協調與信息傳遞
- 事件的功能=通知+可選的事件參數
- 原理:事件模型中的兩個“5”
- “發生->響應”中的5個部分:事件的擁有者,事件的響應者,事件,事件處理器,事件訂閱
- “發生->響應”中的5個動作:
(1)我有一個事件
(2)一個人或者一群人關心(即“訂閱”)我這個事件
(3)我的這個事件發生了
(4)關心這個事件的人會被依次通知到
(5)被通知的人根據拿到的信息(即“事件數據”、“事件參數”、“通知”)對事件進行響應(即“事件處理”)
- 事件的本質是委托字段的一個包裝器。
二、事件的應用
事件模型的五個組成部分:
- 事件的擁有者(event source,對象)
- 事件(event,成員)
- 事件的響應者(event subscriber,對象)
- 事件處理器(event handler,成員)——本質上是一個回調方法
- 事件訂閱——把事件處理器和事件關聯在一起,本質上是一種以委托類型為基礎的“約定”
using System.Timers;
namespace EventExample
{class Program{static void Main(string[] args){System.Timers.Timer timer = new System.Timers.Timer();//1.事件的擁有者timer.Interval = 1000;Boy boy = new Boy();//3.事件的響應者//2.事件:Elapsedtimer.Elapsed += new ElapsedEventHandler( boy.Action);//5.訂閱事件timer.Start();Console.ReadLine(); }}class Boy{//4.事件處理器internal void Action(object? sender, ElapsedEventArgs e){Console.WriteLine("Jump");}}}
- 第一種組合模式:事件的擁有者和事件的響應者是不同的對象
namespace EventExample2
{internal static class Program{static void Main(){Form form = new Form();Controller controller = new Controller(form);form.ShowDialog();}}class Controller {private Form form;public Controller(Form form ){if (form != null) {this.form = form;this.form.Click += this.FormClicked;}}private void FormClicked(object sender, EventArgs e){this.form.Text = DateTime.Now.ToString();}}
}
- 第二種組合模式:事件的擁有者和時間的響應者是同一個對象
namespace EventExample3
{internal static class Program{static void Main(){MyForm form = new MyForm();form.Click += form.FormClicked;form.ShowDialog();}}class MyForm : Form{internal void FormClicked(object sender, EventArgs e){this.Text = DateTime.Now.ToString();}}}
-
第三張組合模式:事件的擁有者是事件的響應者的一個字段成員
namespace EventExample4
{internal static class Program{static void Main(){MyForm form = new MyForm(); form.ShowDialog();}}class MyForm : Form{private TextBox textBox;private Button button;public MyForm(){this.textBox = new TextBox();this.button = new Button();this.button.Text = "Say Hello!";this.button.Top = 30;this.button.Click += this.ButtonClicked;this.Controls.Add(this.textBox);this.Controls.Add(this.button);}private void ButtonClicked(object sender, EventArgs e){this.textBox.Text = "Hello world!";}}}
訂閱的幾種寫法
//方法一:直接掛載處理器this.button1.Click += Button1_Click;//方法二:使用委托this.button1.Click += new EventHandler(this.Button1_Click);//方法三:使用委托this.button1.Click += delegate (object? sender, EventArgs e){this.Text = DateTime.Now.ToString();};//簡寫this.button1.Click += (sender, e)=>{this.Text = DateTime.Now.ToString();};
三、事件的自定義聲明
完整聲明
- 規定輸出類型和輸入參數
- 根據規定聲明委托
- 在事件擁有者類中聲明委托字段
- 根據委托聲明事件
- 訂閱事件(把委托和響應事件綁定)
- 調用委托
(相對于間接調用了響應事件)
namespace EventExample
{class Program{public static void Main(string[] args){Customer customer = new Customer();Waiter waiter = new Waiter();customer.Order += waiter.Action;customer.Action();customer.PayTheBill();}}public class OrderEventArgs : EventArgs{public string DishName { get; set; }public string Size { get; set; }}//聲明委托public delegate void OrderEventHandler(Customer customer, OrderEventArgs e);public class Customer{//聲明委托字段private OrderEventHandler? orderEventHandlerOrder;//聲明事件public event OrderEventHandler Order{add{this.orderEventHandlerOrder += value;}remove{this.orderEventHandlerOrder -= value;}}public double Bill { get; set; }public void PayTheBill(){Console.WriteLine("I will pay ${0}.", this.Bill);}public void WalkIn(){Console.WriteLine("Walk into the restaurant.");}public void SitDown(){Console.WriteLine("Sit down.");}public void Think(){for (int i = 0; i < 5; i++){Console.WriteLine("Let me think...");Thread.Sleep(1000);}if (this.orderEventHandlerOrder != null){OrderEventArgs e = new OrderEventArgs();e.DishName = "辣椒擂皮蛋";e.Size = "large";this.orderEventHandlerOrder.Invoke(this, e);}}public void Action(){Console.ReadLine();this.WalkIn();this.SitDown();this.Think();}}public class Waiter{internal void Action(Customer customer, OrderEventArgs e){Console.WriteLine("I will serve you the dish -{0}.", e.DishName);double price = 10;switch (e.Size){case "small":price = price * 0.5;break;case "large":price = price * 1.5;break;}customer.Bill += price;}}}
簡略聲明
public class Customer{//簡略聲明事件public event OrderEventHandler Order;....public void Think(){...if (this.Order != null){...this.Order.Invoke(this, e);}}public void Action(){...this.Think();}}
使用EventHandler
聲明事件
public delegate void EventHandler(object? sender, EventArgs e);
public class Customer{//使用EventHandler 聲明事件public event EventHandler Order;...}public class Waiter{internal void Action(Object sender, EventArgs e){//強制轉換Customer? customer = sender as Customer;OrderEventArgs? orderInfo = e as OrderEventArgs;...}}
注意:
- 一般事件命名為
××EventHandler
- 事件參數命名為
××EventArgs
- 觸發事件命名為
On××
,訪問級別為protected
修改后的代碼
public class Customer{...this.OnOrder("辣椒擂皮蛋", "large"); }private void OnOrder(string dishName, string size) {if (this.Order != null){OrderEventArgs e = new OrderEventArgs();e.DishName = dishName;e.Size = size;this.Order.Invoke(this, e);}}...}