事件

来源:http://www.cnblogs.com/liunlls/archive/2016/10/29/event.html
-Advertisement-
Play Games

事件的定義過程 定義類型來容納所有需要發送給事件通知接收者的附加信息 簡單的說,就是調用事件的時候能夠傳遞一些參數信息 定義事件成員 事件成員類型為 ,意味著‘事件通知’的所有接收者都必須提供一個原型和 委托類型相匹配的回調方法, 所以方法原型必須具有以下形式 定義負責引發事件的方法來通知事件的登記 ...


事件的定義過程

定義類型來容納所有需要發送給事件通知接收者的附加信息

簡單的說,就是調用事件的時候能夠傳遞一些參數信息

    internal class NewMailEventArgs : EventArgs
    {
        private readonly string m_from, m_to, m_subject;
        public NewMailEventArgs(string from, string to, string subject)
        {
            m_from = from;
            m_to = to;
            m_subject = subject;
        }

        public string From { get { return m_from; } }
        public string To { get { return m_to; } }
        public string Subject { get { return m_subject; } }
    }

定義事件成員

    internal class MailManager
    {
        //事件成員,關鍵字event
        public event EventHandler<NewMailEventArgs> NewMail;
    }

事件成員類型為EventHandler<NewMailEventArgs>,意味著‘事件通知’的所有接收者都必須提供一個原型和EventHandler<NewMailEventArgs>委托類型相匹配的回調方法,
// 表示將處理事件的方法 [Serializable] public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e);
所以方法原型必須具有以下形式

 //事件模式要求所有方法返回值都是void,因為引發事件後可能會回調好幾個方法,但是沒法獲取所有方法的返回值
 void methodname(object sender, NewMailEventArgs e);

定義負責引發事件的方法來通知事件的登記對象

要調用事件時,當前類及其派生類中的代碼會調用該方法。該方法要獲取一個參數(NewMailEventArgs對象,這個對象中包含了傳給通知接收對象的信息)

    internal class MailManager
    {
        //事件成員關鍵字event
        public event EventHandler<NewMailEventArgs> NewMail;

        protected virtual void OnNewMail(NewMailEventArgs e) {
            //出於線程安全的考慮,現在將對委托欄位的引用複製到一個臨時欄位中
            EventHandler<NewMailEventArgs> temp = Interlocked.CompareExchange(ref NewMail, null, null);
            if (temp!=null)
            {
                temp(this, e);
            }

            //在.Net初期,是建議用以下這種方式的,但是問題在於,當線程發現NewMail不為null,
            //然後在調用NewMail(this, e)之前,另一個線程從委托鏈中移除了委托,使NewMail變為了null,
            //這樣就引發了空異常,為了避免這個問題,推薦用上面的方式
            //if (NewMail != null)
            //{
            //    NewMail(this, e);
            //}
        }
    }

為了方便,我們可以定義一個擴展方法

    public static class EventArgsExtensions
    {
        public static void Raise<TEventArgs>(this TEventArgs e, object sender, ref EventHandler<TEventArgs> handler) 
        where TEventArgs:EventArgs
        {
            EventHandler<TEventArgs> temp = Interlocked.CompareExchange(ref handler, null, null);
            if (handler!=null)
            {
                handler(sender, e);
            }
        }
    }

這樣在調用的時候就簡單多了

        protected virtual void OnNewMail(NewMailEventArgs e)
        {
            e.Raise<NewMailEventArgs>(this, ref NewMail);
        }

定義方法將輸入轉換為期望事件

    internal class MailManager
    {
        //事件成員關鍵字event
        public event EventHandler<NewMailEventArgs> NewMail;

        protected virtual void OnNewMail(NewMailEventArgs e)
        {
            e.Raise<NewMailEventArgs>(this, ref NewMail);
        }

        //定義一個方法,將輸入轉換為期望事件
        public void SimulateNewEmail(string from, string to, string subject)
        {
            //調用虛方法通知對象事件已發生
            //如果沒有類重寫該方法,我們的對象通知事件的所有登記對象
            OnNewMail(new NewMailEventArgs(from, to, subject));
        }
    }

設計偵聽事件的類型

    internal sealed class Fax
    {
        public Fax(MailManager m)
        {
            //向MailManager的NewMail事件登記我們的回調方式
            m.NewMail += m_NewMail;
        }

        void m_NewMail(object sender, NewMailEventArgs e)
        {
            Console.WriteLine("Faxing mail message:");
            Console.WriteLine(" From:{0},to:{1},Subject:{2}",e.From,e.To,e.Subject);
        }

        //執行這個方法,Fax對象將取消對NewMail事件的關註
        public void Unregister(MailManager m)
        {
            m.NewMail -= m_NewMail;
        }
    }

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 狀態模式筆記 當一個對象的內部狀態發生改變時,會導致行為的改變,這像是改變了對象 狀態模式既是解決程式中臃腫的分支判斷語句問題,將每個分支轉化為一種狀態獨立出來,方便每種狀態的管理又不至於每次執行時遍歷所有分支 主要目的:將條件判斷的不同結果轉化為狀態對象的內部狀態,既然是狀態對象的內部狀態,所以作 ...
  • <DOCTYPE html> <thml lang = "en"> <head> <meta charset = "UTF-8"> <title>空間</title> <style type = "text/css"> *{ padding : 0; margin : 0; } ul{ list-s ...
  • 大家好,我是Traceless,很高興能得到作者 幸運★星 大佬的授權,為大家整理框架使用教程及開發文檔,本文及立足於基礎科普,包含框架原理介紹、開發環境、使用環境搭建及日常框架使用說明。對開發老鳥來說,說許你只需要翻閱使用環境、插件使用和下載API介面文檔即可。 此處要對框架的版權等信息做一個說明 ...
  • 首先,實現環境VS2013+windows10。 程式界面預覽: 瀏覽器可以實現搜索,新建,關閉功能。簡單的基礎功能都能實現。 下麵是代碼: 從上到下的講解: 1.標題 2.頂部菜單 ToolStrip控制項 (1)步驟: 1)拖入ToolStirp控制項。 2)編輯ToolStrip選項button。 ...
  • using System; using System.Collections.Generic; using System.Linq; using System.Text; //泛型解決原來集合類中元素的裝箱和拆箱問題 namespace _012 { class Program { static v ...
  • 不同的瀏覽器會把cookie文件保存在不同的地方 以下是C# WebBrowser控制項cookies的存放路徑 C:\Users\{你的帳號名}\AppData\Local\Microsoft\Windows\INetCookies cookies文件格式請查看相關資料 下麵是清除cookies的代 ...
  • using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace _011 { //枚舉為值類型,不是引用類型 enum en_um { 畢畢, 男人, a = 1, b = ...
  • C 介面的顯示實現和隱示實現 public interface IReview { void GetReviews(); } public class ShopReview :IReview { public void GetReviews(){} } 這種方式是隱示實現: IReview rv = ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...