.NET 事件模型教程(二)
目录
复制
保存
public event [委托类型] [事件名称];
复制
保存
public event [委托类型] [事件名称] { add { .... } remove { .... } }
复制
保存
public delegate void StartWorkEventHandler(object sender,StartWorkEventArgs e); public delegate void RateReportEventHandler(object sender,RateReportEventArgs e); // 注意:本例中的实现,仅支持“单播事件”。 // 如需要“多播事件”支持,请参考 Demo 1H 的实现。 // 为每种事件生成一个唯一的 object 作为键 static readonly object StartWorkEventKey = new object(); static readonly object EndWorkEventKey = new object(); static readonly object RateReportEventKey = new object(); // 使用 Hashtable 存储事件处理程序 private Hashtable handlers = new Hashtable(); // 使用 protected 方法而没有直接将 handlers.Add / handlers.Remove // 写入事件 add / remove 访问器,是因为: // 如果 Worker 具有子类的话, // 我们不希望子类可以直接访问、修改 handlers 这个 Hashtable。 // 并且,子类如果有其他的事件定义, // 也可以使用基类的这几个方法方便的增减事件处理程序。 protected void AddEventHandler(object eventKey,Delegate handler) { lock (this) { if (handlers[eventKey] == null) { handlers.Add(eventKey,handler); } else { handlers[eventKey] = handler; } } } protected void RemoveEventHandler(object eventKey) { lock (this) { handlers.Remove(eventKey); } } protected Delegate GetEventHandler(object eventKey) { return (Delegate) handlers[eventKey]; } // 使用了 add 和 remove 访问器的事件声明 public event StartWorkEventHandler StartWork { add { AddEventHandler(StartWorkEventKey,value); } remove { RemoveEventHandler(StartWorkEventKey); } } public event EventHandler EndWork { add { AddEventHandler(EndWorkEventKey,value); } remove { RemoveEventHandler(EndWorkEventKey); } } public event RateReportEventHandler RateReport { add { AddEventHandler(RateReportEventKey,value); } remove { RemoveEventHandler(RateReportEventKey); } } // 此处需要做些相应调整 protected virtual void OnStartWork(StartWorkEventArgs e) { StartWorkEventHandler handler = (StartWorkEventHandler) GetEventHandler(StartWorkEventKey); if (handler != null) { handler(this,e); } } protected virtual void OnEndWork(EventArgs e) { EventHandler handler = (EventHandler) GetEventHandler(EndWorkEventKey); if (handler != null) { handler(this,e); } } protected virtual void OnRateReport(RateReportEventArgs e) { RateReportEventHandler handler = (RateReportEventHandler) GetEventHandler(RateReportEventKey); if (handler != null) { handler(this,e); } } public Worker() { } public void DoLongTimeTask() { int i; bool t = false; double rate; OnStartWork(new StartWorkEventArgs(MAX)); for (i = 0; i <= MAX; i++) { Thread.Sleep(1); t = !t; rate = (double) i / (double) MAX; OnRateReport(new RateReportEventArgs(rate)); } OnEndWork(EventArgs.Empty); }
复制
// 为每种事件生成一个唯一的键
static readonly object StartWorkEventKey = new object();
static readonly object EndWorkEventKey = new object();
static readonly object RateReportEventKey = new object();
// 为外部挂接的每一个事件处理程序,生成一个唯一的键
private object EventHandlerKey
{
get { return new object(); }
}
// 对比 Demo 1G,
// 为了支持“多播”,
// 这里使用两个 Hashtable:一个记录 handlers,
// 另一个记录这些 handler 分别对应的 event 类型(event 的类型用各自不同的 eventKey 来表示)。
// 两个 Hashtable 都使用 handlerKey 作为键。
// 使用 Hashtable 存储事件处理程序
private Hashtable handlers = new Hashtable();
// 另一个 Hashtable 存储这些 handler 对应的事件类型
private Hashtable events = new Hashtable();
protected void AddEventHandler(object eventKey,Delegate handler)
{
// 注意添加时,首先取了一个 object 作为 handler 的 key,
// 并分别作为两个 Hashtable 的键。
lock (this)
{
object handlerKey = EventHandlerKey;
handlers.Add(handlerKey,handler);
events.Add(handlerKey,eventKey);
}
}
protected void RemoveEventHandler(object eventKey,Delegate handler)
{
// 移除时,遍历 events,对每一个符合 eventKey 的项,
// 分别检查其在 handlers 中的对应项,
// 如果两者都吻合,同时移除 events 和 handlers 中的对应项。
//
// 或许还有更简单的算法,不过我一时想不出来了 :(
lock (this)
{
foreach (object handlerKey in events.Keys)
{
if (events[handlerKey] == eventKey)
{
if ((Delegate) handlers[handlerKey] == handler)
{
handlers.Remove(handlers[handlerKey]);
events.Remove(events[handlerKey]);
break;
}
}
}
}
}
protected ArrayList GetEventHandlers(object eventKey)
{
ArrayList t = new ArrayList();
lock (this)
{
foreach (object handlerKey in events.Keys)
{
if (events[handlerKey] == eventKey)
{
t.Add(handlers[handlerKey]);
}
}
}
return t;
}
// 使用了 add 和 remove 访问器的事件声明
public event StartWorkEventHandler StartWork
{
add { AddEventHandler(StartWorkEventKey,value); }
remove { RemoveEventHandler(StartWorkEventKey,value); }
}
public event EventHandler EndWork
{
add { AddEventHandler(EndWorkEventKey,value); }
remove { RemoveEventHandler(EndWorkEventKey,value); }
}
public event RateReportEventHandler RateReport
{
add { AddEventHandler(RateReportEventKey,value); }
remove { RemoveEventHandler(RateReportEventKey,value); }
}
// 此处需要做些相应调整
protected virtual void OnStartWork(StartWorkEventArgs e)
{
ArrayList handlers = GetEventHandlers(StartWorkEventKey);
foreach (StartWorkEventHandler handler in handlers)
{
handler(this,e);
}
}
protected virtual void OnEndWork(EventArgs e)
{
ArrayList handlers = GetEventHandlers(EndWorkEventKey);
foreach (EventHandler handler in handlers)
{
handler(this,e);
}
}
protected virtual void OnRateReport(RateReportEventArgs e)
{
ArrayList handlers = GetEventHandlers(RateReportEventKey);
foreach (RateReportEventHandler handler in handlers)
{
handler(this,e);
}
}
上面给出的算法,只是给你做参考,应该还有比这个实现更简单、更高效的方式。 为了实现“多播事件”,这次使用了两个Hashtable:一个存储“handlerKey-handler”对,一个存储“handlerKey-eventKey”对。相信通过仔细研读,你可以读懂这段代码。我就不再赘述了。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |