用 C# 做组件设计时的事件实现方法讨论
生活随笔
收集整理的這篇文章主要介紹了
用 C# 做组件设计时的事件实现方法讨论
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
事件,其實就是將物體的某個過程處理通過委托(delegate, 也就是函數指針) 的方式公開給外部的自定義函數處理。 C# 可以使用多播委托,但實際上一般情況下只需要用到單播。
事件需要通過調用到那個委托的代碼觸發才可以被調用。
以下用例子來說明。首先我們定義一個委托:
最簡單的事件定義方式:
namespace EventDemo { public class Class1 { private event ProcessHandler _processHandler = null; public event ProcessHandler ProcessStart { add { _processHandler += value; } remove { _processHandler -= value; } } /// /// 觸發事件的某個方法 /// public void Process() { _processHandler(this); for (int i = 0; i < 10; i++) i = i + 1; } public Class1() { } } }
Class1 使用原始的事件定義方式, 有一個問題,如果事件非常多的時候,每一個事件都要對應一個相應的私有的委托成員(函數指針)。在窗口程序里尤其可怕,因為 Windows 窗口消息數以千計。這樣會造成很龐大的內存消耗。
這個模式需要改進為 Class2。代碼如下:
Class2 中,每一種事件定義一個相應的靜態變量作為他們在 Hashtable 中的 keys.
Hashtable 作為函數指針的容器,是私有的。
這樣實際上是 Lazy Allocate 模式,大大減小了內存的開銷。
但該實現也有問題,因為每個 key 只對應一個 value,所以不能支持 multicast 的事件。
在 .net 中,通常繼承自 Component 類來實現這種基礎架構。代碼如下:
Component 類的實現是完整的,支持 Multicast 委托。我們用 Reflector 看一下該類的代碼,會看到有一個叫做 EventHandlerList 的類,代碼如下:
public sealed class EventHandlerList : IDisposable { // Methods public EventHandlerList() { } public void AddHandler(object key, Delegate 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); } } public void Dispose() { this.head = null; } private EventHandlerList.ListEntry Find(object key) { EventHandlerList.ListEntry entry1 = this.head; while (entry1 != null) { if (entry1.key == key) { break; } entry1 = entry1.next; } return entry1; } public void RemoveHandler(object key, Delegate value) { EventHandlerList.ListEntry entry1 = this.Find(key); if (entry1 != null) { entry1.handler = Delegate.Remove(entry1.handler, value); } } // Properties public Delegate this[object key] { get { EventHandlerList.ListEntry entry1 = this.Find(key); if (entry1 != null) { return entry1.handler; } return null; } set { EventHandlerList.ListEntry entry1 = this.Find(key); if (entry1 != null) { entry1.handler = value; } else { this.head = new EventHandlerList.ListEntry(key, value, this.head); } } } // Fields private ListEntry head; // Nested Types private sealed class ListEntry { // Methods public ListEntry(object key, Delegate handler, EventHandlerList.ListEntry next) { this.next = next; this.key = key; this.handler = handler; } // Fields internal Delegate handler; internal object key; internal EventHandlerList.ListEntry next; } }
這個類實現了一個事件的鏈表數據結構。其中每一個具體的事件是采用 Delegate.Combine(), Delegate.Remove() 方法來添加和刪除具體的 delegate. 所以這個的實現和 Class2 的實現相比功能更加完整了。
Component 類的代碼是這樣的:
[DesignerCategory("Component")] public class Component : MarshalByRefObject, IComponent, IDisposable { private EventHandlerList events; protected EventHandlerList Events { get { if (this.events == null) { this.events = new EventHandlerList(); } return this.events; } } // ... }
它簡單的通過提供 Events 這個屬性,讓設計者可以自由的實現各種屬性。
(注:本文的 Class1 ~ Class3 代碼范例來自黃忠成的《深入剖析 asp.net 組件設計》一書。)
轉載于:https://www.cnblogs.com/chinhr/archive/2008/04/11/1147885.html
總結
以上是生活随笔為你收集整理的用 C# 做组件设计时的事件实现方法讨论的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: XP风格界面
- 下一篇: c#中拖动图片的例子