首先從controlInstance.Click事件開始. 用Reflector反編譯System.Windows.Forms.Control類可以看到對Click事件的定義:
public event EventHandler Click
{
add
{
base.Events.AddHandler(Control.EventClick, value);
}
remove
{
base.Events.RemoveHandler(Control.EventClick, value);
}
}
這裏的Control.EventClick是一個只讀的靜態私有屬性,它是以後事件查找委託的鍵(key),請記住這個.
Control的Events屬性是由System.ComponentModel.Component 繼承而來,它是EventHandlerList的實例.
protected EventHandlerList Events
{
get
{
if (this.events == null)
{
this.events = new EventHandlerList();
}
return this.events;
}
}
EventHandlerList類有三個重要的方法:
public void RemoveHandler(object key, Delegate value);
private ListEntry Find(object key);
AddHandler的作用是插入一個鍵和一個委託類型的值, 插入之前通過Find方法檢查一下同樣的委託對象是否存在,如果存在,則合併; 如果不存在,以要插入的委託對象(value)爲頭.
{
EventHandlerList.ListEntry entry1 = this.Find(key);
if (entry1 != null)
{
entry1.handler = Delegate.Combine(entry1.handler, value);
}
else
{
this.head = new EventHandlerList.ListEntry(key, value, this.head);
}
}
如果是一個按鈕的Click事件,我們一般定義爲:
protected void OnButtonClick(object sender, System.EventArgs e)
{
// 你的處理函數
}
則通過了button1.Events.AddHandler(Control.EventClick, EventHandler handler),而這個handler卻是一個MulticastDelegate的實例。看MS公佈的.net framework 部分源碼就知道了:
//
//
// Copyright (c) 2002 Microsoft Corporation. All rights reserved.
//
// The use and distribution terms for this software are contained in the file
// named license.txt, which can be found in the root of this distribution.
// By using this software in any fashion, you are agreeing to be bound by the
// terms of this license.
//
// You must not remove this notice, or any other, from this software.
//
//
// ==--==
namespace System {
using System;
/// <include file='doc\EventHandler.uex' path='docs/doc[@for="EventHandler"]/*' />
[Serializable()]
public delegate void EventHandler(Object sender, EventArgs e);}
現在我們轉到對委託(Delegate)和多播委託(MulticastDelegate)的研究了。
Delegate類已經封裝好產生委託,消除委託和執行委法的方法,它是一個不能實例化的抽象類。但.net 的編譯器支持由delegate定義的類型來實例化一個Delegate對象,它能讓這個對象的執行委託方法像普通函數一樣調用(具體的可以看C#高級編程裏面的實例),所以很多時候,delegate類型會被認爲是函數指針。
Delegate還有兩個很重要的方法,組合委託Combine和刪除委託Remove。在單播委託Delegate中使用這組合委託方法會拋出多播不支持異常(MulticastNotSupportedException)。而使用刪除委託方法時,如果這個單播委託和要刪除的委託是同一個值時,則返回null,證明已經刪除;如果不是,則原封不動返回原來的單播委託。
EventHandler實際上是一個多播委託實例,所以它支持組合委託和刪除委託的方法。這個實例,實際上是一個委託實例鏈,它是這個鏈的鏈尾。每次像調用普通函數調用這個委託的時候,這個委託會執行完委託的代理函數,並查找鏈表中上一個委託實例,執行這個委託的代理函數,再查找鏈表中上上個委託實例,執行當前委託的代理函數。。。 一直到鏈表被遍歷完。
{
if (_prev != null)
_prev.DynamicInvokeImpl(args);
return base.DynamicInvokeImpl(args);
}
好了。那可以想象,一個用戶點擊按鈕button1,首先執行的函數是OnClick函數
protected virtual void OnClick(EventArgs e)
{
if (this.CanRaiseEvents)
{
EventHandler handler1 = (EventHandler) base.Events[Control.EventClick];
if (handler1 != null)
{
handler1(this, e);
}
}
}