是什么
本文討論類型中定義的最后一種成員:事件
定義了時間成員的類型允許類型通知其他對象發生了特定的事情。
具體的說,定義了時間成員的類型能提供以下功能:
- 方法能登記它對事件的關注
- 方法能注銷它對事件的關注
- 事件發生時,登記了的方法將收到通知
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#》的小栗子自己更改了一點,希望對你有幫助。