欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

深入了解C#設(shè)計(jì)模式之訂閱發(fā)布模式

 更新時(shí)間:2020年06月24日 14:46:14   作者:HueiFeng  
這篇文章主要介紹了C#設(shè)計(jì)模式之訂閱發(fā)布模式的的相關(guān)資料,文中示例代碼非常詳細(xì),供大家參考和學(xué)習(xí),感興趣的朋友可以了解下

什么是Pub-Sub

發(fā)布訂閱是一種設(shè)計(jì)模式,它允許應(yīng)用程序組件之間進(jìn)行松散耦合。
其實(shí)訂閱發(fā)布設(shè)計(jì)中主要是發(fā)布者生成事件通道,用于在不了解任何訂閱者存在的情況下通知訂閱者。

當(dāng)然委托EventHandlers和Event關(guān)鍵字在此事件處理機(jī)制中擔(dān)任著重要的角色。下面我們來(lái)看看如何使用它們。

Pub和Sub的使用

首先我們看一個(gè)簡(jiǎn)單地訂閱發(fā)布模式.

定義一個(gè)Action委托,無(wú)返回值.

namespace PubSubPattern
{
  public class Pub
  {
    public Action OnChange { get; set; }

    public void Raise()
    {
      if (OnChange != null)
      {
        //Invoke OnChange Action
        OnChange();
      }
    }
  }

  class Program
  {
    static void Main(string[] args)
    {
      var p = new Pub();
      p.OnChange += () => Console.WriteLine("Sub 1");

      p.OnChange += () => Console.WriteLine("Sub 2");

      p.Raise();

      Console.WriteLine("Press enter !");
      Console.ReadLine();

    }
  }
}

如上代碼我們創(chuàng)建了一個(gè)發(fā)布者,并且我們調(diào)用委托進(jìn)行創(chuàng)建我們匿名方法來(lái)訂閱。由于委托提供了多播功能,因此我們可以O(shè)nChange屬性上使用+=.

雖然說(shuō)我們看著如上代碼執(zhí)行無(wú)誤,但是程序中仍然存在一些問(wèn)題,如果使用=而不是+=,那么OnChange屬性中將會(huì)刪除第一個(gè)訂閱者。
由于OnChange是公共屬性,因此該類的任何外部用戶都可以進(jìn)行調(diào)用p.OnChange().

使用Event關(guān)鍵字的發(fā)布訂閱

下面我們來(lái)看看使用event關(guān)鍵字后的代碼

  public class Pub
  {
    public event Action OnChange = delegate { };

    public void Raise()
    {
      OnChange();
    }
  }

  class Program
  {
    static void Main(string[] args)
    {
      Pub p = new Pub();
      p.OnChange += () => Console.WriteLine("Sub 1");
      p.OnChange += () => Console.WriteLine("Sub 2");
      p.Raise();
      Console.WriteLine("Press enter !");
      Console.ReadLine();
    }
  }

通過(guò)如上代碼我們?cè)囍ソ鉀Q我們第一處所說(shuō)的問(wèn)題,我們會(huì)發(fā)現(xiàn)使用event關(guān)鍵字后可以保護(hù)我們OnChange免受不必要的訪問(wèn)。它不允許使用=也就是說(shuō)他不允許直接進(jìn)行分配委托,因此我們現(xiàn)在可以避免使用=,從而避免應(yīng)用程序不必要的麻煩。

可能大家也會(huì)發(fā)現(xiàn)OnChange初始化為空委托delegate{}。這樣可以確保我們的OnChange永遠(yuǎn)不會(huì)為空。因?yàn)楫?dāng)我們其他進(jìn)行對(duì)他調(diào)用的時(shí)候我們可以在代碼中進(jìn)行刪除對(duì)他的非空檢查.

使用EventHandlers的發(fā)布訂閱

其實(shí)在訂閱發(fā)布中,發(fā)布者和訂閱者都不知道彼此的存在。有個(gè)EventHandler,它被稱為消息代理或者說(shuō)事件總線,發(fā)布者和訂閱者都應(yīng)該知道它,它接收所有傳入的消息并且將它們進(jìn)行轉(zhuǎn)發(fā).

因此呢,在如下片段中我們使用EventHandler而不是用Action.

public delegate void EventHandler(
  object sender,
  EventArgs e
)

默認(rèn)情況下,EventHandler將發(fā)送對(duì)象和一些事件參數(shù)作為參數(shù)。

 public class MyEventArgs : EventArgs
    {
      public int Value { get; set; }

      public MyEventArgs(int value)
      {
        Value = value;
      }
    }

    public class Pub
    {
      public event EventHandler<MyEventArgs> OnChange = delegate { };
      public void Raise()
      {
        OnChange(this, new MyEventArgs(1));
      }
    }
    class Program
    {
      static void Main(string[] args)
      {
        Pub p = new Pub();
        p.OnChange += (sender, e) => Console.WriteLine("Sub 1.Value:" + e.Value);
        p.OnChange += (sender, e) => Console.WriteLine("Sub 2.Value:" + e.Value);
        p.Raise();
        Console.WriteLine("Press enter !");
        Console.ReadLine();
      }
    }

如上代碼中通過(guò)pub類使用通用的EventHandler,它觸發(fā)EventHandler OnChange時(shí)需要傳遞的事件參數(shù)類型,在上面代碼片段中為MyArgs

事件中的異常

我們繼續(xù)說(shuō)一種情況.大家看如下代碼片段

  public class MyEventArgs : EventArgs
  {
    public int Value { get; set; }

    public MyEventArgs(int value)
    {
      Value = value;
    }
  }

  public class Pub
  {
    public event EventHandler<MyEventArgs> OnChange = delegate { };
    public void Raise()
    {
      OnChange(this, new MyEventArgs(1));
    }
  }
  class Program
  {
    static void Main(string[] args)
    {
      Pub p = new Pub();
      p.OnChange += (sender, e) => Console.WriteLine("Sub 1.Value:" + e.Value);
      p.OnChange += (sender, e) => { throw new Exception(); };
      p.OnChange += (sender, e) => Console.WriteLine("Sub 2.Value:" + e.Value);
      p.Raise();
      Console.WriteLine("Press enter !");
      Console.ReadLine();
    }
  }

運(yùn)行如上代碼后,大家會(huì)發(fā)現(xiàn)第一個(gè)訂閱者已經(jīng)執(zhí)行成功了,第二個(gè)訂閱者引發(fā)了異常,而第三個(gè)訂閱者未被調(diào)用.這是一個(gè)很尷尬的事情.

如果說(shuō)我們覺(jué)得如上的過(guò)程不是我們預(yù)期的,我們需要手動(dòng)引發(fā)事件并處理異常,這時(shí)候我們可以使用Delegate基類中定義的GetInvoctionList來(lái)幫助我們實(shí)現(xiàn)這些。

我們繼續(xù)看如下代碼

public class MyEventArgs : EventArgs
    {
      public int Value { get; set; }

      public MyEventArgs(int value)
      {
        Value = value;
      }
    }

    public class Pub
    {

      public event EventHandler<MyEventArgs> OnChange = delegate { };

      public void Raise()
      {
        MyEventArgs eventArgs = new MyEventArgs(1);

        List<Exception> exceptions = new List<Exception>();

        foreach (Delegate handler in OnChange.GetInvocationList())
        {
          try
          {
            handler.DynamicInvoke(this, eventArgs);
          }
          catch (Exception e)
          {
            exceptions.Add(e);
          }
        }

        if (exceptions.Any())
        {
          throw new AggregateException(exceptions);
        }
      }
    }
    class Program
    {
      static void Main(string[] args)
      {
        Pub p = new Pub();
        p.OnChange += (sender, e) => Console.WriteLine("Sub 1.Value:" + e.Value);
        p.OnChange += (sender, e) => { throw new Exception(); };
        p.OnChange += (sender, e) => Console.WriteLine("Sub 2.Value:" + e.Value);
        p.Raise();
        Console.WriteLine("Press enter !");
        Console.ReadLine();
      }
    }

Reference

https://github.com/hueifeng/DesignPatterns-Samples/tree/master/PubSubPattern

https://hackernoon.com/observer-vs-pub-sub-pattern-50d3b27f838c

以上就是深入了解C#設(shè)計(jì)模式之訂閱發(fā)布模式的詳細(xì)內(nèi)容,更多關(guān)于c# 訂閱發(fā)布模式的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C#編程實(shí)現(xiàn)連接SQL SERVER數(shù)據(jù)庫(kù)實(shí)例詳解

    C#編程實(shí)現(xiàn)連接SQL SERVER數(shù)據(jù)庫(kù)實(shí)例詳解

    這篇文章主要介紹了C#編程實(shí)現(xiàn)連接SQL SERVER數(shù)據(jù)庫(kù)的方法,以實(shí)例形式較為詳細(xì)的分析了C#連接SQL SERVER數(shù)據(jù)庫(kù)的相關(guān)步驟與具體實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2015-11-11
  • C#創(chuàng)建及訪問(wèn)網(wǎng)絡(luò)硬盤的實(shí)現(xiàn)

    C#創(chuàng)建及訪問(wèn)網(wǎng)絡(luò)硬盤的實(shí)現(xiàn)

    本文主要介紹了C#創(chuàng)建及訪問(wèn)網(wǎng)絡(luò)硬盤的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • C# 設(shè)計(jì)模式系列教程-抽象工廠模式

    C# 設(shè)計(jì)模式系列教程-抽象工廠模式

    抽象工廠模式為創(chuàng)建一組相關(guān)或相互依賴的對(duì)象提供一個(gè)接口,而且無(wú)需指定他們的具體類。
    2016-06-06
  • C#中的不可變數(shù)據(jù)類型介紹(不可變對(duì)象、不可變集合)

    C#中的不可變數(shù)據(jù)類型介紹(不可變對(duì)象、不可變集合)

    這篇文章主要介紹了C#中的不可變數(shù)據(jù)類型介紹(不可變對(duì)象、不可變集合),本文講解了不可變對(duì)象、自定義不可變集合、Net提供的不可變集合、不可變優(yōu)點(diǎn)、不可變對(duì)象缺點(diǎn)等內(nèi)容,需要的朋友可以參考下
    2015-04-04
  • C#使用IronPython調(diào)用Python的實(shí)現(xiàn)

    C#使用IronPython調(diào)用Python的實(shí)現(xiàn)

    本文主要介紹了C#使用IronPython調(diào)用Python的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • C#實(shí)戰(zhàn)之備忘錄的制作詳解

    C#實(shí)戰(zhàn)之備忘錄的制作詳解

    這篇文章主要為大家介紹了如何利用C#制作一個(gè)備忘錄,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C#有一定的幫助,感興趣的小伙伴可以學(xué)習(xí)一下
    2022-02-02
  • C#實(shí)現(xiàn)文件與Base64的相互轉(zhuǎn)換

    C#實(shí)現(xiàn)文件與Base64的相互轉(zhuǎn)換

    本文主要介紹了C#實(shí)現(xiàn)文件與Base64的相互轉(zhuǎn)換,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • C#枚舉類型與結(jié)構(gòu)類型實(shí)例解析

    C#枚舉類型與結(jié)構(gòu)類型實(shí)例解析

    這篇文章主要介紹了C#枚舉類型與結(jié)構(gòu)類型實(shí)例,需要的朋友可以參考下
    2014-07-07
  • 詳解C# 線程的掛起與喚醒

    詳解C# 線程的掛起與喚醒

    這篇文章主要介紹了詳解C# 線程的掛起與喚醒,幫助大家更好的理解和學(xué)習(xí)使用c#,感興趣的朋友可以了解下
    2021-05-05
  • WPF制作帶小箭頭的按鈕完整代碼

    WPF制作帶小箭頭的按鈕完整代碼

    WPF(Windows Presentation Foundation)是微軟推出的基于Windows 的用戶界面框架。下面通過(guò)本文給大家介紹WPF制作帶小箭頭的按鈕完整代碼,需要的朋友參考下吧
    2017-12-12

最新評(píng)論