本文讨论类型中定义的最后一种成员:事件
定义了时间成员的类型允许类型通知其他对象发生了特定的事情。
具体的说,定义了时间成员的类型能提供以下功能:
CLR事件模型以委托为基础。委托是调用回调方法的一种类型安全的方式。
本文我们将通过一个小栗子来学习一下事件怎么使用:
假定有个bolg平台可以订阅文章,用户A、B、C可以通过订阅或取消订阅来接收或者不接受此平台的文章。即,我是管理员,我在blog上发了一篇文章,那么订阅blog的用户就可以收到这篇文章了。
下面我们来实现这个功能,顺便来学习下事件的使用:
约定:这种类型应该从System.EventArgs
派生,而且类名以EventArgs
结束。
internal class BlogEventArgs : EventArgs{ PRivate readonly String author, content; private DateTime tdate; public BlogEventArgs(string author,string content,DateTime date) { this.author = author; this.content = content; this.tdate = date; } public string Author { get { return author;} } public string Content { get { return content; } } public DateTime TDate { get { return tdate;} }}
约定:事件使用event
关键字。每个事件成员要指定以下内容:可访问性标识符;委托类型;以及名称。
internal class BlogManager{ public event EventHandler<BlogEventArgs> NewBlog;}
约定:类要定义一个受保护的虚方法。引发事件时,类及其派生类中的代码回调用该方法。方法只接受一个参数,即BlogEventArgs
对象
protected virtual void OnNewBlog(BlogEventArgs e) { EventHandler<BlogEventArgs> temp = Volatile.Read(ref NewBlog); if (temp!=null) { temp(this, e); } }
关于为什么要像上边这样写,只能说这样是线程安全的方式引发事件,其他方式可能会有线程方面的问题。
在BlogManager
中,调用WriteNewBlog
来指出写了一篇新博客
public void WriteNewBlog(string author, string content, DateTime date) { BlogEventArgs e = new BlogEventArgs(author,content,date); OnNewBlog(e); }
比如User
类型想订阅或取消这个博客
internal sealed class Reader{ public Reader(BlogManager blogManager) { blogManager.NewBlog += blogManager_NewBlog; } void blogManager_NewBlog(object sender, BlogEventArgs e) { Console.WriteLine("读者已收到博客!"); Console.WriteLine("作者:{0},内容:{1},发表时间:{2}",e.Author,e.Content,e.TDate.ToShortTimeString()); } public void Unregister(BlogManager bmManager) { bmManager.NewBlog -= blogManager_NewBlog; }}
class Program{ static void Main(string[] args) { BlogManager bmManager = new BlogManager(); Reader readerA =new Reader(bmManager); bmManager.WriteNewBlog("1号作者", "这是我的第一篇文章", DateTime.Now); readerA.Unregister(bmManager); bmManager.WriteNewBlog("1号作者", "这是我的第二篇文章,应该收不到", DateTime.Now); Console.ReadKey(); }}
根据书本《CLR via C#》的小栗子自己更改了一点,希望对你有帮助。
新闻热点
疑难解答