一、淺談委托
如果有個過winform 和webform 程序開發的小伙伴一定有個這樣的感覺吧,點擊Button直接就執行了那個方法,到此他是怎么實現了的呢,大家有考慮過沒有?
回到正題,什么是委托呢?委托,我們可以把看着是一個作為方法參數的一個方法,為什么呢,因為委托可以作為作為方法的參數,而給委托賦的值都是方法。下面我舉一個例
/// <summary>
/// 定義的一個打招呼的委托 /// </summary> /// <param name="name"></param> public delegate void GreetingDelegate(string name); /// <summary> /// 中國人打招呼的類 /// </summary> public class Chinese { public void ChineseGreeting(string name) { Console.Write("早上好--" + name); } } public class English { public void EnglishGreeting(string name) { Console.Write("Good Morning--" + name); } } class Program { static void Main(string[] args) { Chinese people1 = new Chinese(); English people2 = new English(); Greeting("歡大少", people1.ChineseGreeting); Console.Write("\n"); Greeting("Master", people2.EnglishGreeting); Console.ReadKey(); } private static void Greeting(string name,GreetingDelegate MakingGreeting ) { MakingGreeting(name); } }
運行結果
當然,實質上委托是一個特殊的類,知識有限,只能講到這兒了,
事件是什么呢,其實事件就是用event修飾后的委托,
class Program { static void Main(string[] args) { Publishser pb = new Publishser(); Subscriber sb = new Subscriber(); //pb.NumberChange += sb.OnNumberChange; pb.NumberChange = sb.OnNumberChange; pb.DoSomething(); pb.NumberChange(100); Console.ReadLine(); } } /// <summary> /// 定義委托 /// </summary> public delegate void NumberChangeEventHandler(int count); public class Publishser { private int count; public NumberChangeEventHandler NumberChange; //public event NumberChangeEventHandler NumberChange; public void DoSomething() { if(NumberChange!=null) { count++; NumberChange(count); } } } public class Subscriber { public void OnNumberChange(int count) { Console.WriteLine("Subscriber notified count ={0}", count); } }
上面的代碼如果是定義普通的委托能夠正常運行,但如果換成事件來的話變異不能通過,為什么呢?因為為了更好的封裝性,實際是事件是一個私有變量,外部不是訪問,如果用委托變量,外部能夠調用委托,影響封裝性,就像上面代碼
pb.NumberChange(100);,如果定義為事件,那么NumberChange只能通過內部方法DoSomething來調用。
事件只能通過+=來進行賦值,如果你反編譯你可以看到事件里有兩個方法 Add() 和Remove(),分別對應的是+=和-=。
二、winform程序click事件的原理
在form的構造函數中,我們能看到下面的代碼
/// <summary> /// 設計器支持所需的方法 - 不要 /// 使用代碼編輯器修改此方法的內容。 /// </summary> private void InitializeComponent() { this.button1 = new System.Windows.Forms.Button(); this.SuspendLayout(); // // button1 // this.button1.Location = new System.Drawing.Point(391, 117); this.button1.Name = "button1"; this.button1.Size = new System.Drawing.Size(75, 23); this.button1.TabIndex = 0; this.button1.Text = "button1"; this.button1.UseVisualStyleBackColor = true; this.button1.Click += new System.EventHandler(this.button1_Click); // // Form1 // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(808, 400); this.Controls.Add(this.button1); this.Name = "Form1"; this.Text = "F1"; this.ResumeLayout(false); }
我們發現對事件的添加 this.button1.Click += new System.EventHandler(this.button1_Click);
這個地方我們只是添加了事件,但這個事件是怎么觸發的呢?我們進行調試
button的click的觸發經過如下過程
三、模擬winform事件
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace MonitorEvent { /// <summary> /// 定義委托 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> public delegate void MonitorEventHandler(object sender, EventArgs e); /// <summary> /// 時間數據類 /// </summary> public class MsgEventArgs : EventArgs { /// <summary> /// 修改時間 /// </summary> public DateTime ChanggeTime { get; set; } /// <summary> /// 提示信息 /// </summary> public string ToSend { get; set; } public MsgEventArgs(DateTime changgeTime, string toSend) { this.ChanggeTime = changgeTime; this.ToSend = toSend; } } /// <summary> /// 事件訂閱者 /// </summary> public class MonitorText { public string name = "文本文檔"; //定義監控文本事件 public event MonitorEventHandler MonitorEvent; //上次文件更新時間用於判斷文件是否修改過 private DateTime _lastWriteTime = File.GetLastWriteTime(@"C:\Users\Administrator\Desktop\1.txt"); public MonitorText() { } // 文件更新調用 protected virtual void OnTextChange(MsgEventArgs e) { if (MonitorEvent != null) { //不為空,處理事件 MonitorEvent(this, e); } } //事件監聽的方法 public void BeginMonitor() { DateTime bCurrentTime; while (true) { bCurrentTime = File.GetLastWriteTime(@"C:\Users\Administrator\Desktop\1.txt"); if (bCurrentTime != _lastWriteTime) { _lastWriteTime = bCurrentTime; MsgEventArgs msg = new MsgEventArgs(bCurrentTime, "文本改變了"); OnTextChange(msg); } //0.1秒監控一次 Thread.Sleep(100); } } } /// <summary> /// 事件監聽者 /// </summary> public class Administrator { //管理員事件處理方法 public void OnTextChange(object Sender, EventArgs e) { MonitorText monitorText = (MonitorText)Sender; Console.WriteLine("尊敬的管理員:" + DateTime.Now.ToString() + ": " + monitorText.name + "發生改變."); } } class Program { static MonitorText MonitorTextEventSource; static void Main(string[] args) { MonitorTextEventSource = new MonitorText(); //1. 啟動后台線程添加監視事件 var thrd = new Thread(MonitorTextEventSource.BeginMonitor); thrd.IsBackground = true; thrd.Start(); //2實例化管理員類 Administrator ad = new Administrator(); //4訂閱事件 MonitorTextEventSource.MonitorEvent += ad.OnTextChange; Console.ReadLine(); } } }
四、申明
文中的觀點多來源與張子陽的.net之美和ATtuing的博客,希望大家共同學習