C# 事件(Event)

事件是對(duì)象發(fā)送的通知,用于表示操作的發(fā)生。.NET中的事件遵循觀察者設(shè)計(jì)模式。

引發(fā)事件的類稱為 Publisher(發(fā)布者),接收通知的類稱為 Subscriber(訂閱者)。一個(gè)事件可以有多個(gè)訂閱者。通常,發(fā)布者在發(fā)生某個(gè)操作時(shí)引發(fā)事件。訂閱者希望在操作發(fā)生時(shí)獲得通知,他們應(yīng)該向事件注冊(cè)并處理它。

在C#中,事件是封裝的委托。它取決于委托。委托為訂閱者類的事件處理程序方法定義簽名。

下圖說(shuō)明了C#中的事件。

活動(dòng)發(fā)布者-訂閱者
事件發(fā)布者和訂閱者

通過(guò)事件使用委托

事件在類中聲明且生成,且通過(guò)使用同一個(gè)類或其他類中的委托與事件處理程序關(guān)聯(lián)。包含事件的類用于發(fā)布事件。這被稱為 發(fā)布者(publisher) 類。其他接受該事件的類被稱為 訂閱者(subscriber) 類。事件使用 發(fā)布-訂閱(publisher-subscriber) 模型。

發(fā)布者(publisher)- 是一個(gè)包含事件和委托定義的對(duì)象。事件和委托之間的聯(lián)系也定義在這個(gè)對(duì)象中。發(fā)布者(publisher)類的對(duì)象調(diào)用這個(gè)事件,并通知其他的對(duì)象。

訂閱者(subscriber)- 是一個(gè)接受事件并提供事件處理程序的對(duì)象。在發(fā)布者(publisher)類中的委托調(diào)用訂閱者(subscriber)類中的方法(事件處理程序)。

聲明事件

可以通過(guò)兩個(gè)步驟聲明一個(gè)事件:

  1. 聲明委托

  2. 使用 event 關(guān)鍵字聲明委托的變量

下面的示例演示如何在發(fā)布者類中聲明事件。

public delegate void Notify();  // 委托
                    
public class ProcessBusinessLogic
{
    public event Notify ProcessCompleted; // 事件

}

在上面的示例中,我們聲明了一個(gè)委托 Notify,然后在 ProcessBusinessLogic 類中使用“event”關(guān)鍵字聲明了委托類型Notify的事件ProcessCompleted。因此,ProcessBusinessLogic類稱為publisher(發(fā)布者)。Notify委托指定ProcessCompleted事件處理程序的簽名。它指定subscriber(訂閱者)類中的事件處理程序方法必須具有 void 返回類型,并且沒(méi)有參數(shù)。

現(xiàn)在,讓我們看看如何引發(fā)ProcessCompleted事件。請(qǐng)看以下實(shí)現(xiàn)。

public delegate void Notify();  // 委托
                    
public class ProcessBusinessLogic
{
    public event Notify ProcessCompleted; // 事件

    public void StartProcess()
    {
        Console.WriteLine("Process Started!");
        // 一些代碼在這里..
        OnProcessCompleted();
    }

    protected virtual void OnProcessCompleted() //受保護(hù)的虛方法
    {
        //如果ProcessCompleted不為null,則調(diào)用委托
        ProcessCompleted?.Invoke(); 
    }
}

上面,StartProcess()方法在末尾調(diào)用onProcessCompleted()方法,這將引發(fā)一個(gè)事件。通常,要引發(fā)事件,應(yīng)使用<EventName>上的名稱定義protected和virtual方法。受保護(hù)和虛擬使派生類重寫(xiě)引發(fā)事件的邏輯。但是,派生類應(yīng)該始終調(diào)用基類的On<EventName>方法,以確保注冊(cè)的委托接收事件。

OnProcessCompleted() 方法使用 ProcessCompleted?. invoke() 調(diào)用委托。這將調(diào)用所有注冊(cè)到 ProcessCompleted 事件的事件處理程序方法。

訂閱者類必須注冊(cè)到ProcessCompleted事件,并使用簽名匹配Notify委托的方法來(lái)處理它,如下所示。

class Program
{
    public static void Main()
    {
        ProcessBusinessLogic bl = new ProcessBusinessLogic();
        bl.ProcessCompleted += bl_ProcessCompleted; // 注冊(cè)事件
        bl.StartProcess();
    }

    // 事件處理程序
    public static void bl_ProcessCompleted()
    {
        Console.WriteLine("Process Completed!");
    }
}

上面,Program 類是 ProcessCompleted 事件的訂閱者。它使用 + = 運(yùn)算符向事件注冊(cè)。請(qǐng)記住,這與我們?cè)诙嗖ノ械恼{(diào)用列表中添加方法的方式是一樣的。bl_processcompleted ()方法處理該事件,因?yàn)樗c Notify 委托的簽名匹配。

內(nèi)置 EventHandler 委托

.NET Framework包含用于最常見(jiàn)事件的內(nèi)置委托類型EventHandler和EventHandler <TEventArgs>。通常,任何事件都應(yīng)包括兩個(gè)參數(shù):事件源和事件數(shù)據(jù)。。對(duì)不包含事件數(shù)據(jù)的所有事件使用EventHandler委托。對(duì)于包含要發(fā)送到處理程序的數(shù)據(jù)的事件,請(qǐng)使用 EventHandler<TEventArgs> 委托。

上面顯示的示例可以使用EventHandler委托,而無(wú)需聲明自定義Notify委托,如下所示。

class Program
{
    public static void Main()
    {
        ProcessBusinessLogic bl = new ProcessBusinessLogic();
        bl.ProcessCompleted += bl_ProcessCompleted; // 事件注冊(cè)
        bl.StartProcess();
    }

    // 事件處理
    public static void bl_ProcessCompleted(object sender, EventArgs e)
    {
        Console.WriteLine("Process Completed!");
    }
}

public class ProcessBusinessLogic
{
    // 使用內(nèi)置EventHandler聲明事件
    public event EventHandler ProcessCompleted; 

    public void StartProcess()
    {
        Console.WriteLine("Process Started!");
        // 一些代碼在這里..
        OnProcessCompleted(EventArgs.Empty); //無(wú)事件數(shù)據(jù)
    }

    protected virtual void OnProcessCompleted(EventArgs e)
    {
        ProcessCompleted?.Invoke(this, e);
    }
}

在上面的示例中,事件處理程序bl_ProcessCompleted()方法包含兩個(gè)與 EventHandler 委托匹配的參數(shù)。同時(shí),傳遞 this 作為發(fā)送者和EventArgs。當(dāng)我們?cè)贠nProcessCompleted()方法中使用Invoke()引發(fā)事件時(shí)為空。因?yàn)槲覀兊氖录恍枰魏螖?shù)據(jù),它只是通知訂閱者流程已經(jīng)完成,所以我們傳遞了 EventArgs.Empty。

傳遞事件數(shù)據(jù)

大多數(shù)事件向訂閱者發(fā)送一些數(shù)據(jù)。EventArgs類是所有事件數(shù)據(jù)類的基類。NET包含許多內(nèi)置事件數(shù)據(jù)類,如 SerialDataReceivedEventArgs。它遵循以EventArgs結(jié)束所有事件數(shù)據(jù)類的命名模式。您可以通過(guò)派生 EventArgs 類為事件數(shù)據(jù)創(chuàng)建自定義類。

使用EventHandler <TEventArgs>將數(shù)據(jù)傳遞到處理程序,如下所示。

class Program
{
    public static void Main()
    {
        ProcessBusinessLogic bl = new ProcessBusinessLogic();
        bl.ProcessCompleted += bl_ProcessCompleted; // 事件注冊(cè)
        bl.StartProcess();
    }

    // 事件處理
    public static void bl_ProcessCompleted(object sender, bool IsSuccessful)
    {
        Console.WriteLine("Process " + (IsSuccessful? "Completed Successfully": "failed"));
    }
}

public class ProcessBusinessLogic
{
    // 使用內(nèi)置EventHandler聲明事件
    public event EventHandler<bool> ProcessCompleted; 

    public void StartProcess()
    {
        try
        {
            Console.WriteLine("Process Started!");
			
            // 一些代碼在這里..

            OnProcessCompleted(true);
        }
        catch(Exception ex)
        {
            OnProcessCompleted(false);
        }
    }

    protected virtual void OnProcessCompleted(bool IsSuccessful)
    {
        ProcessCompleted?.Invoke(this, IsSuccessful);
    }
}

在上面的示例中,我們將單個(gè)布爾值傳遞給處理程序,以指示該過(guò)程是否成功完成。

如果希望將多個(gè)值作為事件數(shù)據(jù)傳遞,那么可以創(chuàng)建一個(gè)從 EventArgs 基類派生的類,如下所示。

class ProcessEventArgs : EventArgs
{
    public bool IsSuccessful { get; set; }
    public DateTime CompletionTime { get; set; }
}

下面的示例演示如何將自定義 ProcessEventArgs 類傳遞給處理程序。

class Program
{
    public static void Main()
    {
        ProcessBusinessLogic bl = new ProcessBusinessLogic();
        bl.ProcessCompleted += bl_ProcessCompleted; // 事件注冊(cè)
        bl.StartProcess();
    }

    // 事件處理
    public static void bl_ProcessCompleted(object sender, ProcessEventArgs e)
    {
        Console.WriteLine("Process " + (e.IsSuccessful? "Completed Successfully": "failed"));
        Console.WriteLine("Completion Time: " + e.CompletionTime.ToLongDateString());
    }
}

public class ProcessBusinessLogic
{
    // 使用內(nèi)置EventHandler聲明事件
    public event EventHandler<ProcessEventArgs> ProcessCompleted; 

    public void StartProcess()
    {
        var data = new ProcessEventArgs();
		
        try
        {
            Console.WriteLine("Process Started!");
			
            // 一些代碼在這里..
            
            data.IsSuccessful = true;
            data.CompletionTime = DateTime.Now;
            OnProcessCompleted(data);
        }
        catch(Exception ex)
        {
            data.IsSuccessful = false;
            data.CompletionTime = DateTime.Now;
            OnProcessCompleted(data);
        }
    }

    protected virtual void OnProcessCompleted(ProcessEventArgs e)
    {
        ProcessCompleted?.Invoke(this, e);
    }
}

因此,您可以在C#中創(chuàng)建,引發(fā),注冊(cè)和處理事件。

要記住的要點(diǎn)

  1. 事件是對(duì)委托的包裝。這取決于委托。

  2. 將“ event”關(guān)鍵字與委托類型變量一起使用來(lái)聲明事件。

  3. 將內(nèi)置委托EventHandler或EventHandler <TEventArgs>用于常見(jiàn)事件。

  4. 發(fā)布者類引發(fā)一個(gè)事件,而訂閱者類注冊(cè)一個(gè)事件并提供事件處理程序方法。

  5. 用事件名稱命名引發(fā)事件的方法,該方法以“ On”為前綴。

  6. 處理程序方法的簽名必須與委托簽名匹配。

  7. 使用+ =運(yùn)算符注冊(cè)事件。使用 -= 運(yùn)算符取消訂閱,不能使用=運(yùn)算符。

  8. 使用EventHandler <TEventArgs>傳遞事件數(shù)據(jù)。

  9. 派生EventArgs基類以創(chuàng)建自定義事件數(shù)據(jù)類。

  10. 可以將事件聲明為靜態(tài),虛擬,密封和抽象(static, virtual, sealed, abstract)。

  11. 接口可以將事件作為成員包含。

  12. 如果有多個(gè)訂閱者,則將同步調(diào)用事件處理程序。

丰满人妻一级特黄a大片,午夜无码免费福利一级,欧美亚洲精品在线,国产婷婷成人久久Av免费高清