日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > C# >内容正文

C#

用 C# 做组件设计时的事件实现方法讨论

發(fā)布時(shí)間:2025/5/22 C# 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 用 C# 做组件设计时的事件实现方法讨论 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

事件,其實(shí)就是將物體的某個(gè)過(guò)程處理通過(guò)委托(delegate, 也就是函數(shù)指針) 的方式公開(kāi)給外部的自定義函數(shù)處理。 C# 可以使用多播委托,但實(shí)際上一般情況下只需要用到單播。

事件需要通過(guò)調(diào)用到那個(gè)委托的代碼觸發(fā)才可以被調(diào)用。
以下用例子來(lái)說(shuō)明。首先我們定義一個(gè)委托:

namespace EventDemo { public delegate void ProcessHandler(object sender); }
最簡(jiǎn)單的事件定義方式:
namespace EventDemo { public class Class1 { private event ProcessHandler _processHandler = null; public event ProcessHandler ProcessStart { add { _processHandler += value; } remove { _processHandler -= value; } } /// /// 觸發(fā)事件的某個(gè)方法 /// public void Process() { _processHandler(this); for (int i = 0; i < 10; i++) i = i + 1; } public Class1() { } } }

Class1 使用原始的事件定義方式, 有一個(gè)問(wèn)題,如果事件非常多的時(shí)候,每一個(gè)事件都要對(duì)應(yīng)一個(gè)相應(yīng)的私有的委托成員(函數(shù)指針)。在窗口程序里尤其可怕,因?yàn)?Windows 窗口消息數(shù)以千計(jì)。這樣會(huì)造成很龐大的內(nèi)存消耗。
這個(gè)模式需要改進(jìn)為 Class2。代碼如下:

namespace EventDemo { using System.Collections; public class Class2 { private Hashtable _eventList = new Hashtable(); // 每一種事件會(huì)對(duì)應(yīng)一個(gè)相應(yīng)的靜態(tài)變量作為他們?cè)?Hashtable 中的 keys. private static object _processStart = new object(); private static object _processEnd = new object(); public event ProcessHandler ProcessStart { add { _eventList.Add(_processStart, value); } remove { _eventList.Remove(_processStart); } } public event ProcessHandler ProcessEnd { add { _eventList.Add(_processEnd, value); } remove { _eventList.Remove(_processEnd); } } public void Process() { ProcessHandler start = (ProcessHandler) _eventList[_processStart]; ProcessHandler end = (ProcessHandler) _eventList[_processEnd]; if (start != null) start(this); for (int i = 0; i < 10; i++) i = i + 1; if (end != null) end(this); } public Class2() { } } }

Class2 中,每一種事件定義一個(gè)相應(yīng)的靜態(tài)變量作為他們?cè)?Hashtable 中的 keys.
Hashtable 作為函數(shù)指針的容器,是私有的。
這樣實(shí)際上是 Lazy Allocate 模式,大大減小了內(nèi)存的開(kāi)銷(xiāo)。
但該實(shí)現(xiàn)也有問(wèn)題,因?yàn)槊總€(gè) key 只對(duì)應(yīng)一個(gè) value,所以不能支持 multicast 的事件。

在 .net 中,通常繼承自 Component 類來(lái)實(shí)現(xiàn)這種基礎(chǔ)架構(gòu)。代碼如下:

namespace EventDemo { using System; using System.ComponentModel; public class Class3 : Component { private static object _processStart = new object(); public event EventHandler ProcessStart { add { Events.AddHandler(_processStart, value); } remove { Events.RemoveHandler(_processStart, value); } } public void Process() { EventHandler handler = (EventHandler) Events[_processStart]; if (handler != null) handler(this, null); } public Class3() { } } }
Component 類的實(shí)現(xiàn)是完整的,支持 Multicast 委托。我們用 Reflector 看一下該類的代碼,會(huì)看到有一個(gè)叫做 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; } }
這個(gè)類實(shí)現(xiàn)了一個(gè)事件的鏈表數(shù)據(jù)結(jié)構(gòu)。其中每一個(gè)具體的事件是采用 Delegate.Combine(), Delegate.Remove() 方法來(lái)添加和刪除具體的 delegate. 所以這個(gè)的實(shí)現(xiàn)和 Class2 的實(shí)現(xiàn)相比功能更加完整了。

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; } } // ... }
它簡(jiǎn)單的通過(guò)提供 Events 這個(gè)屬性,讓設(shè)計(jì)者可以自由的實(shí)現(xiàn)各種屬性。

(注:本文的 Class1 ~ Class3 代碼范例來(lái)自黃忠成的《深入剖析 asp.net 組件設(shè)計(jì)》一書(shū)。)

轉(zhuǎn)載于:https://www.cnblogs.com/chinhr/archive/2008/04/11/1147885.html

總結(jié)

以上是生活随笔為你收集整理的用 C# 做组件设计时的事件实现方法讨论的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。