• 软件测试技术
  • 软件测试博客
  • 软件测试视频
  • 开源软件测试技术
  • 软件测试论坛
  • 软件测试沙龙
  • 软件测试资料下载
  • 软件测试杂志
  • 软件测试人才招聘
    暂时没有公告

字号: | 推荐给好友 上一篇 | 下一篇

.Net边学边讲(三)

发布: 2007-6-30 18:56 | 作者: admin | 来源: | 查看: 14次 | 进入软件测试论坛讨论

领测软件测试网 谈到event,就不能不先说一下callback和delegate
如果你使用过C的话,你应该知道有一个函数叫qsort,是用来给数组排序的。但这个函数显然不能承担广泛意义上的比较,因此你需要传递一个指针,他指向具有比较功能的函数。qsort在每次要比较数组元素时都要调用这个函数。这就是callback的概念,在.Net里也可以实现回调,方法是创建一个接口,实现他,传递一个实现此接口的对象的引用。delegate呢,你可以将他理解成一个安全的函数指针。
Notifications跟callback有点类似,但比简单的回调要复杂的多。callback意味着要调用的callback方法被调用的同时要调用的建立callback的方法。这是一个很紧密的耦合。而Notification则要松散一些,你可以注册将来某段时间会或者不会发生的Notification,只当他们发生时处理,否则不用。
你也许想让你写的组件当一些事情发生时通知其他组件,例如,你想写一个按钮组件,当你Click的时候你可能想通知其他组件,而其他组件将不得不准备向你请求Notification,你就要提供一个方法告诉他们你已经有一个可用的Notification。另一方面,你可能也是当其它组件的一些事情发生时希望被通知的人。这时你就需要找到那个特定组件可以提供什么Notification。
在.Net中event是一个你用来广播、引发、处理Notification的机制。大致是这样的,可以引发事件的组件声明这一事件。而希望处理某一特定组件的某一特定事件的组件通过传递一个方法的delegate向引发事件的组件注册。这样,当事件发生时引发事件的组件就会调用每个已注册的方法。通过delegate和event我们可以实现异步调用的功能。在C#中是这样声明一个代理的:public delegate void LogHandler(String message);代理在处理这种回调时已经是很强大了。但是当我们需要代理被存储以便以后的Notification,就有一点麻烦了。比如说我们有一个对象Button,有一个Click事件。我们可以声明一个ClickHandler 的代理类型用于处理Click事件,在我们的Button的Class中声明一个ClickHandler的public实例,这样其他组件希望Click发生时被通知,就可以简单的把他的代理加到Click代理中去。myButton.Click += new ClickHandler(MyMethod);
看上去着好像没什么问题。但是这里却存在一个大问题,我们声明Click代理是public,这违反了我们以前说过的data fields永远不要声明成public,这会有一系列麻烦。解决的办法是声明成private或protected,然后用属性解决读写。这样我们可以private声明Click,在写一对public方法去增加一个listener及减少一个listener。当然在.Net中,当你声明一个event时,.Net已经为你做好这一切了。声明一个事件:
class AlarmTimer {
public event EventHandler Alarm;
// ...
}
这段代码说明AlarmTimer可以向所有其它对象广播它可以引发一个叫Alarm的事件。Alarm事件用的是EventHandler代理类型。EventHandler:无返回值、接受两个参数(Object:指向事件的发送者,EventArgs:包含关于事件的数据)
看一个例子:
class AlarmTimer {
public event EventHandler Alarm;
private Timer myTimer;
public AlarmTimer() {
myTimer = new Timer();
myTimer.Tick += new EventHandler(OnTick);
}
public void Set(Double seconds) {
myTimer.Interval = (Int32)(seconds * 1000);
myTimer.Start();
}
protected void OnTick(Object sender, EventArgs e) {
myTimer.Stop();
if (Alarm != null) Alarm(this, EventArgs.Empty);
}
public void ReEnable() {
myTimer.Enabled = true;
}
}
注意AlarmTimer既引发事件(Alarm)又处理事件(Timer中的Tick事件)
static AlarmTimer myAlarm = new AlarmTimer();
public static void TestEvent() {
myAlarm.Alarm += new EventHandler(TimerEventProcessor);
myAlarm.Set(2);
Console.WriteLine("Timer is set; alarm will go off in two seconds");
Application.Run();
}
//处理事件
private static void TimerEventProcessor(
Object myObject, EventArgs myEventArgs) {
if (MessageBox.Show("Wake up! Continue ringing?",
"Count is: " + alarmCounter,
MessageBox.YesNo) == DialogResult.Yes) {
alarmCounter += 1;
myAlarm.ReEnable();
}
else {
Application.Exit();
}
}
注意:Object和EventArgs不是必需的参数,只是这是一个好的写法模式而已
关于event还有好多没有说,留着以后慢慢说吧。


延伸阅读

文章来源于领测软件测试网 https://www.ltesting.net/


关于领测软件测试网 | 领测软件测试网合作伙伴 | 广告服务 | 投稿指南 | 联系我们 | 网站地图 | 友情链接
版权所有(C) 2003-2010 TestAge(领测软件测试网)|领测国际科技(北京)有限公司|软件测试工程师培训网 All Rights Reserved
北京市海淀区中关村南大街9号北京理工科技大厦1402室 京ICP备2023014753号-2
技术支持和业务联系:info@testage.com.cn 电话:010-51297073

软件测试 | 领测国际ISTQBISTQB官网TMMiTMMi认证国际软件测试工程师认证领测软件测试网