CLR事件機(jī)制建立在委托機(jī)制上
class MailManager
{
public class MailEventArgs : EventArgs
{
public MailEventArgs(
String from,
String to,
String subject,
String body)
{
this.from = from;
this.to = to;
this.subject = subject;
this.body = body;
}
public readonly String from, to, subject, body;
}
public delegate void MailEventHandler(Object sender, MailEventArgs e);
public event MailEventHandler MailMsg;
protected virtual void OnMailMsg(MailEventArgs e)
{
if (MailMsg != null)
{
MailMsg(this, e);
}
}
public virtual void SimulateArrivingMsg(String from, String to, String subject, String body)
{
MailEventArgs e = new MailEventArgs(from, to, subject, body);
OnMailMsg(e);
}
}
以上是一個事件類型定義,簡單步驟:
1.定義一個類型,保存所有傳遞參數(shù)。
.net框架規(guī)定所有的信息類型繼承于EventArgs,類型名稱以EventArgs結(jié)束,EventArgs原型如下:
[Serializable]
public class EventArgs
{
public static readonly EventArgs Empty = new EventArgs();
public EventArgs(){};
}
只有一個靜態(tài)的Empty成員,因為事件中有些不需要額外的參數(shù)信息,所以只要提供EventArgs.Empty,不需要在構(gòu)造新的對象
2.定義一個委托類型,指定事件觸發(fā)時調(diào)用的函數(shù)原型
public delegate void MailEventHandler(Object sender, MailEventArgs e);
如果事件中并沒有額外的傳遞信息,則可以使用System.EventHandler,原型為
public delegate void EventHandler(Object sender,EventArgs e);
3.定義一個事件成員
public event MailEventHandler MailMsg;
4.定義受保護(hù)的虛方法,通知事件登記對象
protected virtual void OnMailMsg(MailEventArgs e);
5.定義驅(qū)動事件方法
public virtual void SimulateArrivingMsg(String from, String to, String subject, String body);
深入理解事件
當(dāng)編譯器遇到public event MailEventHandler MailMsg;
會產(chǎn)生3個構(gòu)造,一個私有委托類型,及add和remove方法
private MailEventHandler MailMsg;
[MethodImplAttribute(MethodImplOptions.Synchronized)]
public virtual void add_MailMsg(MailEventHandler handler)
{
MailMsg = (MailEventHandler)Delegate.Combine(MailMsg, handler);
}
[MethodImplAttribute(MethodImplOptions.Synchronized)]
public virtual void remove_MailMsg(MailEventHandler handler)
{
MailMsg = (MailEventHandler)Delegate.Remove(MailMsg, handler);
}
通過MailMsg內(nèi)_prev字段可以將添加的注冊對象保存
偵聽事件
class Fax
{
public Fax(MailManager mm)
{
mm.MailMsg += new MailManager.MailEventHandler(FaxMsg);
}
private void FaxMsg(Object sender, MailManager.MailEventArgs e)
{
}
public void UnRegister(MailManager mm)
{
MailManager.MailEventHandler callback = new MailManager.MailEventHandler(FaxMsg);
mm.MailMsg -= callback;
}
}
注意,當(dāng)一個對象仍然登記有另外一個對象的事件,該對象就不可能對垃圾回收,如果我們類實現(xiàn)了IDisposable接口,那我們應(yīng)該在
Dispose理注銷所有登記事件
顯示控制事件注冊
private MailEventHandler mailMsgEventHandlerDelegate;
public event MailEventHandler MailMsg
{
add
{
mailMsgEventHandlerDelegate =(MailEventHandler)Delegate.Combine(mailMsgEventHandlerDelegate, value);
}
remove
{
mailMsgEventHandlerDelegate = (MailEventHandler)Delegate.Remove(mailMsgEventHandlerDelegate, value);
}
}
protected virtual void OnMailMsg(MailEventArgs e)
{
if (MailMsg != null)
{
mailMsgEventHandlerDelegate(this, e);
}
}
來代替public event MailEventHandler MailMsg;定義
當(dāng)一個類型中含有多個事件時,由于每個事件事例聲明都將產(chǎn)生委托字段,所以推薦 不要提供公共的事件成員變量,使用事件訪問器替換這些變量
class EventHandlerSet:IDisposable
{
private Hashtable events = new Hashtable();
public virtual Delegate this[Object eventKey]
{
get
{
return (Delegate)events[eventKey];
}
set
{
events[eventKey] = value;
}
}
public virtual void AddHandler(Object eventKey,Delegate handler)
{
events[eventKey] = Delegate.Combine((Delegate)events[eventKey], handler);
}
public virtual void RevHandler(Object eventKey, Delegate handler)
{
events[eventKey] = Delegate.Remove((Delegate)events[eventKey], handler);
}
public virtual void Fire(Object eventKey, Object sender, EventArgs e)
{
Delegate d = (Delegate)events[eventKey];
if (d != null)
d.DynamicInvoke(new Object[]{sender,e});
}
public void Dispose()
{
events = null;
}
public static EventHandlerSet Synchronized(EventHandlerSet eventHandlerSet)
{
if (eventHandlerSet == null)
throw new ArgumentNullException("eventHandlerSet");
return new SynchronizedEventHandlerSet(eventHandlerSet);
}
public class SynchronizedEventHandlerSet : EventHandlerSet
{
private EventHandlerSet eventHandlerSet;
public SynchronizedEventHandlerSet(EventHandlerSet eventHandlerSet)
{
this.eventHandlerSet = eventHandlerSet;
Dispose();
}
public override Delegate this[object eventKey]
{
[MethodImpl(MethodImplOptions.Synchronized)]
get
{
return eventHandlerSet[eventKey];
}
set
{
eventHandlerSet[eventKey] = value;
}
}
[MethodImpl(MethodImplOptions.Synchronized)]
public override void AddHandler(object eventKey, Delegate handler)
{
eventHandlerSet.AddHandler(eventKey, handler);
}
[MethodImpl(MethodImplOptions.Synchronized)]
public override void RevHandler(object eventKey, Delegate handler)
{
eventHandlerSet.RevHandler(eventKey, handler);
}
[MethodImpl(MethodImplOptions.Synchronized)]
public override void Fire(object eventKey, object sender, EventArgs e)
{
eventHandlerSet.Fire(eventKey, sender, e);
}
}
}
class TypeWithLotsEvents
{
protected EventHandlerSet eventSet = EventHandlerSet.Synchronized(new EventHandlerSet());
protected static readonly Object fooEventKey = new Object();
public class FooEventArgs : EventArgs { };
public delegate void FooEventHandler(Object sender, FooEventArgs e);
public event FooEventHandler Foo
{
add
{
eventSet.AddHandler(fooEventKey, value);
}
remove
{
eventSet.AddHandler(fooEventKey, value);
}
}
protected virtual void OnFoo(FooEventArgs e)
{
eventSet.Fire(fooEventKey, this, e);
}
public void SimulateFoo()
{
OnFoo(new FooEventArgs());
}
}
以上是microsoft .net 框架設(shè)計一個example,如果設(shè)計該種事件類型,其中給出了EventHandlerSet的實現(xiàn),
.net框架中也有類似的事件 EventHandlerList,但是訪問效率和線程同步有缺陷,所以有需要我們自己提供
EventHandlerSet實現(xiàn).詳情請參考microsoft .net 框架設(shè)計
posted on 2010-09-30 14:17
小果子 閱讀(425)
評論(0) 編輯 收藏 引用 所屬分類:
.Net