帶你一步步的了解“C#事件”機制


是什么

本文討論類型中定義的最后一種成員:事件
定義了時間成員的類型允許類型通知其他對象發生了特定的事情。
具體的說,定義了時間成員的類型能提供以下功能:

  • 方法能登記它對事件的關注
  • 方法能注銷它對事件的關注
  • 事件發生時,登記了的方法將收到通知

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#》的小栗子自己更改了一點,希望對你有幫助。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM