CLR事件机制建立在委托机制上
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.定义一个类型,保存所有传递参数。
.net框架规定所有的信息类型继承于EventArgs,类型名称以EventArgs结束,EventArgs原型如下:
[Serializable]
public class EventArgs
{
public static readonly EventArgs Empty = new EventArgs();
public EventArgs(){};
}
只有一个静态的Empty成员,因为事件中有些不需要额外的参数信息,所以只要提供EventArgs.Empty,不需要在构造新的对象
2.定义一个委托类型,指定事件触发时调用的函数原型
public delegate void MailEventHandler(Object sender, MailEventArgs e);
如果事件中并没有额外的传递信息,则可以使用System.EventHandler,原型为
public delegate void EventHandler(Object sender,EventArgs e);
3.定义一个事件成员
public event MailEventHandler MailMsg;
4.定义受保护的虚方法,通知事件登记对象
protected virtual void OnMailMsg(MailEventArgs e);
5.定义驱动事件方法
public virtual void SimulateArrivingMsg(String from, String to, String subject, String body);
深入理解事件
当编译器遇到public event MailEventHandler MailMsg;
会产生3个构造,一个私有委托类型,及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内_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;
}
}
注意,当一个对象仍然登记有另外一个对象的事件,该对象就不可能对垃圾回收,如果我们类实现了IDisposable接口,那我们应该在
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;定义
当一个类型中含有多个事件时,由于每个事件事例声明都将产生委托字段,所以推荐 不要提供公共的事件成员变量,使用事件访问器替换这些变量
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 框架设计一个example,如果设计该种事件类型,其中给出了EventHandlerSet的实现,
.net框架中也有类似的事件 EventHandlerList,但是访问效率和线程同步有缺陷,所以有需要我们自己提供
EventHandlerSet实现.详情请参考microsoft .net 框架设计
posted on 2010-09-30 14:17
小果子 阅读(418)
评论(0) 编辑 收藏 引用 所属分类:
.Net