委托与事件

委托与事件
  最近在看《C# 3.0学习指南》这本书,重温了一下C#的一些基础知识,另有一番感悟。对于委托与事件有了进一步的了解,以下是三个书上的示例,
  在此处记录一下。

 

1.委托示例:

/*
 
 * 假设有一个类叫MediaStorage,这个类用来存储和管理不现类型的媒体文件——音频文件、视频文件、动画文件等。文件类型对这个类来说并不重要
 * 。更进一步考虑,假设要求这个类能够确保播放的文件可以播放成功,并且报告是否播放成功,那么MediaStore不需要知道如何播放文件,只需要
 * 接收一个标志是否播放成功的代码。
 * 所以可以使用委托,这个委托没有参数,但要求返回值为int类型,返回值表示是否播放成功,0--成功,其他值表示播放不成功,
 * 注:这个方法没有方法体。
*/

 

代码
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;


namespace WindowsApplication1.Library
{
public class DeleExample
{

}
public class MediaStoreage
{
public delegate int PlayMedia();
public void ReportResult(PlayMedia playerDeldgate)
{
if (playerDeldgate()==0)
{
MessageBox.Show(
"影片播放失败!");
}
else
{
MessageBox.Show(
"影片播放失败!");
}
}
}

public class AudioPlayer
{
private int audioPalyerStatus;
public int PlayAudioFile()
{
MessageBox.Show(
"正在播放音乐!");
audioPalyerStatus
= 0;
return audioPalyerStatus;
}
}
public class VideoPlayer
{
private int videoPalyerStatus;
public int PlayVideoFile()
{
MessageBox.Show(
"正在播放影片!");
videoPalyerStatus
= -1;
return videoPalyerStatus;
}
}
public class Tester
{
public void Run()
{
MediaStoreage myMediaStorage
= new MediaStoreage();
//实例货两个媒体播放器
AudioPlayer audioPlayer = new AudioPlayer();
VideoPlayer videoPalyer
= new VideoPlayer();
//实例化委托
MediaStoreage.PlayMedia audioPlayerDelegate = new MediaStoreage.PlayMedia(audioPlayer.PlayAudioFile);
MediaStoreage.PlayMedia videoPlayerDelegate
= new MediaStoreage.PlayMedia(videoPalyer.PlayVideoFile);

//调用委托
myMediaStorage.ReportResult(audioPlayerDelegate);
myMediaStorage.ReportResult(videoPlayerDelegate);
}
}
}


 


2.通知与订阅
/*
    在这个示例中如果SecondChanged不使用+=而是=,则会发生只执行其中的一个方法,而另一个方法则不执行。
 * 2.是其他方法能够直接调用 委托 SecondChangeHandler。
    此示例有一定的不足之处。
*/

代码

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace WindowsApplication1.Library.DeleExample3
{

/// <summary>
/// 保存事件相关信息的类
/// </summary>
public class TimeInfoEventArgs:EventArgs
{
public int hour;
public int minute;
public int second;

public TimeInfoEventArgs(int hour,int minute,int second)
{
this.hour = hour;
this.minute = minute;
this.second = second;
}
}
/// <summary>
/// 发布者,其他类观察这个类
/// 这个类发布一个委托,SecondChangeHandler
/// </summary>
public class Clock
{
private int hour;
private int minute;
private int second;

//订阅者必须实现该委托
public delegate void SecondChangeHandler(object clock, TimeInfoEventArgs timeInformation);
//委托的一个实例
//是一个多点委托域,最初没有引用任何内容。
public SecondChangeHandler SecondChanged;

//设置时钟运行
//将每秒触发一次事件
public void Run()
{
for (; ; )
{
//休眠100毫秒
Thread.Sleep(100);
//取得当前时间
System.DateTime dt = DateTime.Now;
//如果秒发生改变
//则通知订阅者
if (dt.Second!=second)
{
//创建TimeInfoEventArgs对象
//将信息传递给订阅者
TimeInfoEventArgs timeInformation = new TimeInfoEventArgs(dt.Hour, dt.Minute, dt.Second);

//如果有订阅者,则通知订阅者
if (SecondChanged!=null)
{
SecondChanged(
this, timeInformation);
}
}
//更新状态
this.second = dt.Second;
this.minute = dt.Minute;
this.hour = dt.Hour;
}
}

}

/// <summary>
/// 订阅者 displayClock 订阅时钟事件
/// displayClock 显示当前时间
/// </summary>
public class DisplayClock
{
//假设一个时钟,订阅这个时钟的SecondChangeHandler事件
public void Subscribe(Clock theClock)
{
//希望被通知时,观察者类创建一个委托实例 ,然后将委托添加到SecondChanged。
theClock.SecondChanged += new Clock.SecondChangeHandler(TimeHasChanged);

}
//该方法实现委托功能
public void TimeHasChanged(object theClock,TimeInfoEventArgs ti)
{
Console.WriteLine(
"当前时间:{0}:{1}:{2}", ti.hour.ToString(), ti.minute.ToString(), ti.second.ToString());

}

}

/// <summary>
/// 第二个订阅者 LogCurrentTime 负责写文件
/// </summary>
public class LogCurrentTime
{
//假设一个时钟,订阅这个时钟的SecondChangeHandler事件
public void Subscribe(Clock theClock)
{
theClock.SecondChanged
+= new Clock.SecondChangeHandler(WriteLogEntry);

}
//该方法实现委托功能
//向文件中写入内容
//这个对象不保持状态
public void WriteLogEntry(object theClock, TimeInfoEventArgs ti)
{
Console.WriteLine(
"写入日志文件:{0}:{1}:{2}", ti.hour.ToString(), ti.minute.ToString(), ti.second.ToString());

}

}
public class Tester
{
public void Run()
{
//创建一个时钟
Clock theClock=new Clock();
//创建显示对象并告诉其订阅 刚刚创建的时钟
DisplayClock dc=new DisplayClock();
dc.Subscribe(theClock);

//创建log对象,并告诉订阅时钟
LogCurrentTime lct=new LogCurrentTime();
lct.Subscribe(theClock);
//启动时钟

theClock.Run();

}
}
}

 


3.事件示例

 

代码
/*

*
* 在通知与订阅示例中如果SecondChanged不使用+=而是=,则会发生只执行其中的一个方法,而另一个方法则不执行。
* 2.是其他方法能够直接调用 委托 SecondChangeHandler。
* Event关键字用来告诉编译器这个委托只能够定义该 委托的类调用,并且 能够被其他类分别使用+=和-=订阅或取消订阅。
* 使用Event关键字将委托转化为事件,并且限制其他类与其交互的能力,从而只能订阅或取消订阅这个事件。
*
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace WindowsApplication1.Library.DeleExample2
{

/// <summary>
/// 保存事件相关信息的类
/// </summary>
public class TimeInfoEventArgs : EventArgs
{
public int hour;
public int minute;
public int second;

public TimeInfoEventArgs(int hour, int minute, int second)
{
this.hour = hour;
this.minute = minute;
this.second = second;
}
}
/// <summary>
/// 发布者,其他类观察这个类
/// 这个类发布一个委托,SecondChangeHandler
/// </summary>
public class Clock
{
private int hour;
private int minute;
private int second;

//订阅者必须实现该委托
public delegate void SecondChangeHandler(object clock, TimeInfoEventArgs timeInformation);
//委托的一个实例
//是一个多点委托域,最初没有引用任何内容。
//添加event关键字
public event SecondChangeHandler SecondChanged;

//设置时钟运行
//将每秒触发一次事件
public void Run()
{
for (; ; )
{
//休眠100毫秒
Thread.Sleep(100);
//取得当前时间
System.DateTime dt = DateTime.Now;
//如果秒发生改变
//则通知订阅者
if (dt.Second != second)
{
//创建TimeInfoEventArgs对象
//将信息传递给订阅者
TimeInfoEventArgs timeInformation = new TimeInfoEventArgs(dt.Hour, dt.Minute, dt.Second);

//如果有订阅者,则通知订阅者
if (SecondChanged != null)
{
SecondChanged(
this, timeInformation);
}
}
//更新状态
this.second = dt.Second;
this.minute = dt.Minute;
this.hour = dt.Hour;
}
}

}

/// <summary>
/// 订阅者 displayClock 订阅时钟事件
/// displayClock 显示当前时间
/// </summary>
public class DisplayClock
{
//假设一个时钟,订阅这个时钟的SecondChangeHandler事件
public void Subscribe(Clock theClock)
{
//希望被通知时,观察者类创建一个委托实例 ,然后将委托添加到SecondChanged。
theClock.SecondChanged += new Clock.SecondChangeHandler(TimeHasChanged);

}
//该方法实现委托功能
public void TimeHasChanged(object theClock, TimeInfoEventArgs ti)
{
Console.WriteLine(
"事件示例,当前时间:{0}:{1}:{2}", ti.hour.ToString(), ti.minute.ToString(), ti.second.ToString());

}

}

/// <summary>
/// 第二个订阅者 LogCurrentTime 负责写文件
/// </summary>
public class LogCurrentTime
{
//假设一个时钟,订阅这个时钟的SecondChangeHandler事件
public void Subscribe(Clock theClock)
{
theClock.SecondChanged
+= new Clock.SecondChangeHandler(WriteLogEntry);

}
//该方法实现委托功能
//向文件中写入内容
//这个对象不保持状态
public void WriteLogEntry(object theClock, TimeInfoEventArgs ti)
{
Console.WriteLine(
"事件示例,写入日志文件:{0}:{1}:{2}", ti.hour.ToString(), ti.minute.ToString(), ti.second.ToString());

}

}
public class Tester
{
public void Run()
{
//创建一个时钟
Clock theClock = new Clock();
//创建显示对象并告诉其订阅 刚刚创建的时钟
DisplayClock dc = new DisplayClock();
dc.Subscribe(theClock);

//创建log对象,并告诉订阅时钟
LogCurrentTime lct = new LogCurrentTime();
lct.Subscribe(theClock);
//启动时钟

theClock.Run();

}
}
}

 

posted @ 2010-12-01 17:29  DotNet菜园  阅读(327)  评论(0)    收藏  举报