zoukankan      html  css  js  c++  java
  • C#实现发布订阅模式

    首先给出项目的结构

    IPublish.cs的源码:

     1 namespace NsWebChat.PublishSubscribe
     2 {
     3     /// <summary>
     4     /// 发布事件基础接口
     5     /// </summary>
     6     public interface IPublish
     7     {
     8         string PublishTag { get; set; }
     9         object PublishData { get; set; }
    10     }
    11 }

    IPubSubCenter.cs的源码:

     1 namespace NsWebChat.PublishSubscribe
     2 {
     3     /// <summary>
     4     /// 订阅发布中心基础接口
     5     /// </summary>
     6     public interface IPubSubCenter
     7     {
     8         /// <summary>
     9         /// 订阅事件
    10         /// </summary>
    11         bool AddSubscribe(string tag, Func<ISubscribe, object, object> method, object data, string name);
    12         bool AddSubscribe(string tag, Func<ISubscribe, object, object> method, string name);
    13         bool AddSubscribe(Subscribe subscribe);
    14         /// <summary>
    15         /// 获得指定事件的订阅列表
    16         /// </summary>
    17         SubscribeList GetSubscribeList(string tag);
    18         /// <summary>
    19         /// 获得订阅
    20         /// </summary>
    21         Subscribe GetSubscribe(string tag, string name);
    22         /// <summary>
    23         /// 删除订阅
    24         /// </summary>
    25         void RemoveSubscribe(string tag, string name);
    26 
    27         /// <summary>
    28         /// 发布事件
    29         /// </summary>
    30         IEnumerable<Object> Publish(string tag, object data);
    31         IEnumerable<Object> Publish(string tag);
    32         IEnumerable<Object> Publish(Publish publish);
    33     }
    34 }

    ISubscribe.cs的源码:

     1 namespace NsWebChat.PublishSubscribe
     2 {
     3     /// <summary>
     4     /// 订阅事件基础接口
     5     /// </summary>
     6     public interface ISubscribe
     7     {
     8         /// <summary>
     9         /// 订阅的事件
    10         /// </summary>
    11         string SubscribeTag { get; set; }
    12         /// <summary>
    13         /// 订阅的名称
    14         /// </summary>
    15         string SubscribeName { get; set; }
    16         /// <summary>
    17         /// 响应发布时传递的参数
    18         /// </summary>
    19         object Data { get; set; }
    20         /// <summary>
    21         /// 响应发布的方法
    22         /// </summary>
    23         Func<ISubscribe, object, object> SubscribeMethod { get; set; }
    24         /// <summary>
    25         /// 调用订阅方法
    26         /// </summary>
    27         object Invoke(object val);
    28     }
    29 }

    Publish.cs的源码:

     1 namespace NsWebChat.PublishSubscribe
     2 {
     3     /// <summary>
     4     /// 发布事件基类
     5     /// </summary>
     6     public class Publish : IPublish
     7     {
     8         private string _publishTag;
     9         private object _publishData;
    10 
    11         public Publish()
    12         {
    13         }
    14 
    15         public Publish(string tag)
    16             : this(tag, new object())
    17         {
    18 
    19         }
    20 
    21         public Publish(string tag, object val)
    22         {
    23             _publishTag = tag;
    24             _publishData = val;
    25         }
    26 
    27         public string PublishTag
    28         {
    29             get
    30             {
    31                 return _publishTag;
    32             }
    33             set
    34             {
    35                 _publishTag = value;
    36             }
    37         }
    38 
    39         public object PublishData
    40         {
    41             get
    42             {
    43                 return _publishData;
    44             }
    45             set
    46             {
    47                 _publishData = value;
    48             }
    49         }
    50     }
    51 }

    PubSubCenter.cs的源码:

      1 namespace NsWebChat.PublishSubscribe
      2 {
      3     /// <summary>
      4     /// 订阅发布中心基类
      5     /// </summary>
      6     public class PubSubCenter : IPubSubCenter
      7 
      8     {
      9         private Dictionary<string, SubscribeList> _pubsubList = new Dictionary<string, SubscribeList>();
     10 
     11         public bool AddSubscribe(string tag, Func<ISubscribe, object, object> method, object data ,string name)
     12         {
     13             Subscribe subscribe = new Subscribe();
     14             subscribe.Data = data;
     15             subscribe.SubscribeMethod = method;
     16             subscribe.SubscribeTag = tag;
     17             subscribe.SubscribeName = name;
     18             return AddSubscribe(subscribe);
     19         }
     20 
     21         public bool AddSubscribe(string tag, Func<ISubscribe, object, object> method, string name)
     22         {
     23             return AddSubscribe(tag, method, new object(),name);
     24         }
     25 
     26         public bool AddSubscribe(Subscribe subscribe)
     27         {
     28             if (subscribe == null)
     29             {
     30                 return false;
     31             }
     32             else
     33             {
     34                 if (String.IsNullOrEmpty(subscribe.SubscribeName))
     35                 {
     36                     return false;
     37                 }
     38                 Subscribe subscribet = GetSubscribe(subscribe.SubscribeTag, subscribe.SubscribeName);
     39                 if (subscribet != null)
     40                 {
     41                     return false;
     42                 }
     43                 else
     44                 {
     45                     if (_pubsubList.ContainsKey(subscribe.SubscribeTag))
     46                     {
     47                         _pubsubList[subscribe.SubscribeTag].Add(subscribe);
     48                     }
     49                     else
     50                     {
     51                         SubscribeList list = new SubscribeList();
     52                         list.Add(subscribe);
     53                         _pubsubList.Add(subscribe.SubscribeTag, list);
     54                     }
     55                     return true;
     56                 }
     57             }
     58         }
     59 
     60         public SubscribeList GetSubscribeList(string tag)
     61         {
     62             if (_pubsubList.ContainsKey(tag))
     63             {
     64                 return _pubsubList[tag];
     65             }
     66             else
     67             {
     68                 return new SubscribeList();
     69             }
     70         }
     71 
     72         public Subscribe GetSubscribe(string tag, string name)
     73         {
     74             if (_pubsubList.ContainsKey(tag))
     75             {
     76                 foreach (Subscribe item in _pubsubList[tag])
     77                 {
     78                     if (item.SubscribeName == name)
     79                     {
     80                         return item;
     81                     }
     82                 }
     83                 return null;
     84             }
     85             else
     86             {
     87                 return null;
     88             }
     89         }
     90 
     91         public void RemoveSubscribe(string tag, string name)
     92         {
     93             Subscribe subscribe = GetSubscribe(tag, name);
     94             _pubsubList[tag].Remove(subscribe);
     95         }
     96 
     97         public IEnumerable<object> Publish(string tag, object data)
     98         {
     99             if (_pubsubList.ContainsKey(tag))
    100             {
    101                 foreach (Subscribe item in _pubsubList[tag])
    102                 {
    103                     yield return item.Invoke(data);
    104                 }
    105             }
    106             else
    107             {
    108                 yield break;
    109             }
    110         }
    111 
    112         public IEnumerable<object> Publish(string tag)
    113         {
    114             return Publish(tag, new object());
    115         }
    116 
    117         public IEnumerable<object> Publish(Publish publish)
    118         {
    119             return Publish(publish.PublishTag, publish.PublishData);
    120         }
    121     }
    122 }

    Subscribe.cs源码:

     1 namespace NsWebChat.PublishSubscribe
     2 {
     3     /// <summary>
     4     /// 订阅事件基类
     5     /// </summary>
     6     public class Subscribe : ISubscribe
     7     {
     8         private object _data;
     9         private Func<ISubscribe, object, object> _subscribeMethod;
    10         private string _subscribeTag;
    11         private string _subscribeName;
    12 
    13         public Subscribe()
    14         {
    15         }
    16 
    17         public Subscribe(string tag, Func<ISubscribe, object, object> method)
    18             : this(tag, method, "")
    19         {
    20 
    21         }
    22 
    23         public Subscribe(string tag, Func<ISubscribe, object, object> method, object data)
    24             : this(tag, method, data, "")
    25         {
    26 
    27         }
    28 
    29         public Subscribe(string tag, Func<ISubscribe, object, object> method,string name)
    30             : this(tag, method, new object(), name)
    31         {
    32 
    33         }
    34 
    35         public Subscribe(string tag, Func<ISubscribe, object, object> method, object data,string name)
    36         {
    37             _data = data;
    38             _subscribeTag = tag;
    39             _subscribeMethod = method;
    40             _subscribeName = name;
    41         }
    42 
    43         public object Data
    44         {
    45             get
    46             {
    47                 return _data;
    48             }
    49             set
    50             {
    51                 _data = value;
    52             }
    53         }
    54 
    55         public Func<ISubscribe, object, object> SubscribeMethod
    56         {
    57             get
    58             {
    59                 return _subscribeMethod;
    60             }
    61             set
    62             {
    63                 _subscribeMethod = value;
    64             }
    65         }
    66 
    67         public object Invoke(object val)
    68         {
    69             return SubscribeMethod(this, val);
    70         }
    71 
    72         public string SubscribeTag
    73         {
    74             get
    75             {
    76                 return _subscribeTag;
    77             }
    78             set
    79             {
    80                 _subscribeTag = value;
    81             }
    82         }
    83 
    84         public string SubscribeName
    85         {
    86             get
    87             {
    88                 return _subscribeName;
    89             }
    90             set
    91             {
    92                 _subscribeName = value;
    93             }
    94         }
    95     }
    96 }

    SubscribeList.cs的源码:

     1 namespace NsWebChat.PublishSubscribe
     2 {
     3     /// <summary>
     4     /// 订阅列表
     5     /// </summary>
     6     public class SubscribeList : IList<Subscribe>
     7     {
     8         private List<Subscribe> subscribes = new List<Subscribe>();
     9 
    10         public int IndexOf(Subscribe item)
    11         {
    12             return subscribes.IndexOf(item);
    13         }
    14 
    15         public void Insert(int index, Subscribe item)
    16         {
    17             subscribes.Insert(index, item);
    18         }
    19 
    20         public void RemoveAt(int index)
    21         {
    22             subscribes.RemoveAt(index);
    23         }
    24 
    25         public Subscribe this[int index]
    26         {
    27             get
    28             {
    29                 return subscribes[index];
    30             }
    31             set
    32             {
    33                 subscribes[index] = value;
    34             }
    35         }
    36 
    37         public void Add(Subscribe item)
    38         {
    39             subscribes.Add(item);
    40         }
    41 
    42         public void Clear()
    43         {
    44             subscribes.Clear();
    45         }
    46 
    47         public bool Contains(Subscribe item)
    48         {
    49             return subscribes.Contains(item);
    50         }
    51 
    52         public void CopyTo(Subscribe[] array, int arrayIndex)
    53         {
    54             subscribes.CopyTo(array, arrayIndex);
    55         }
    56 
    57         public int Count
    58         {
    59             get
    60             {
    61                 return subscribes.Count;
    62             }
    63         }
    64 
    65         public bool IsReadOnly
    66         {
    67             get { return false; }
    68         }
    69 
    70         public bool Remove(Subscribe item)
    71         {
    72             return subscribes.Remove(item);
    73         }
    74 
    75         public IEnumerator<Subscribe> GetEnumerator()
    76         {
    77             return subscribes.GetEnumerator();
    78         }
    79 
    80         System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    81         {
    82             return subscribes.GetEnumerator();
    83         }
    84     }
    85 }

    下面是单元测试的源码(PubSubCenterTest.cs):

      1 namespace WebChatUnitTest
      2 {
      3     [TestClass]
      4     public class PubSubCenterTest
      5     {
      6         public object Test1(ISubscribe subscribe, object data)
      7         {
      8             Assert.IsTrue(subscribe.Data == data);
      9             return data;
     10         }
     11 
     12         public object Test2(ISubscribe s, object d)
     13         {
     14             return d;
     15         }
     16 
     17         public object Test3(ISubscribe s, object d)
     18         {
     19             return d;
     20         }
     21 
     22         public object Test4(ISubscribe s, object d)
     23         {
     24             return d;
     25         }
     26 
     27         public object Test5(ISubscribe s, object d)
     28         {
     29             return s.SubscribeName;
     30         }
     31 
     32         //测试删除订阅
     33         [TestMethod]
     34         public void TestRemoveSubscribe()
     35         {
     36             PubSubCenter pbc = new PubSubCenter();
     37             pbc.AddSubscribe("t1", Test5, "1");
     38             pbc.AddSubscribe("t1", Test5, "2");
     39             pbc.RemoveSubscribe("t1", "2");
     40             List<string> al = new List<string>();
     41             foreach (string item in pbc.Publish("t1"))
     42             {
     43                 al.Add(item);
     44             }
     45             Assert.IsTrue(al.Count == 1);
     46             Assert.IsTrue(al[0] == "1");
     47             pbc.AddSubscribe("t1", Test5, "2");
     48             pbc.RemoveSubscribe("t1", "1");
     49             al.Clear();
     50             foreach (string item in pbc.Publish("t1"))
     51             {
     52                 al.Add(item);
     53             }
     54             Assert.IsTrue(al.Count == 1);
     55             Assert.IsTrue(al[0] == "2");
     56         }
     57 
     58         //测试重载版本的订阅发布
     59         [TestMethod]
     60         public void TestMoreSubscribeAndPublish()
     61         {
     62             PubSubCenter pbc = new PubSubCenter();
     63             Subscribe subscribe = new Subscribe("t1", Test2, "2", "1");
     64             Subscribe subscribe2 = new Subscribe("t1", Test2, "2");
     65             Subscribe subscribe3 = new Subscribe();
     66             subscribe3.SubscribeMethod = Test2;
     67             subscribe3.SubscribeName = "3";
     68             subscribe3.SubscribeTag = "t1";
     69             pbc.AddSubscribe(subscribe);
     70             pbc.AddSubscribe(subscribe2);
     71             pbc.AddSubscribe(subscribe3);
     72             pbc.AddSubscribe("t1", Test2, "4");
     73             pbc.AddSubscribe("t1", Test2, "2", "5");
     74             List<object> al = new List<object>();
     75             foreach (object item in pbc.Publish("t1"))
     76             {
     77                 al.Add(item);
     78             }
     79             Assert.IsTrue(al.Count == 5);
     80             Assert.IsNotNull(al[0]);
     81             Assert.IsNotNull(al[1]);
     82             Assert.IsNotNull(al[2]);
     83             Assert.IsNotNull(al[3]);
     84             Assert.IsNotNull(al[4]);
     85             al.Clear();
     86             foreach (object item in pbc.Publish("t1","2"))
     87             {
     88                 al.Add(item);
     89             }
     90             Assert.IsTrue(al.Count == 5);
     91             Assert.IsNotNull(al[0]);
     92             Assert.IsNotNull(al[1]);
     93             Assert.IsNotNull(al[2]);
     94             Assert.IsNotNull(al[3]);
     95             Assert.IsNotNull(al[4]);
     96 
     97             Publish pub = new Publish("t1");
     98             al.Clear();
     99             foreach (object item in pbc.Publish(pub))
    100             {
    101                 al.Add(item);
    102             }
    103             Assert.IsTrue(al.Count == 5);
    104             Assert.IsNotNull(al[0]);
    105             Assert.IsNotNull(al[1]);
    106             Assert.IsNotNull(al[2]);
    107             Assert.IsNotNull(al[3]);
    108             Assert.IsNotNull(al[4]);
    109 
    110             pub = new Publish("t1", "2");
    111             al.Clear();
    112             foreach (object item in pbc.Publish(pub))
    113             {
    114                 al.Add(item);
    115             }
    116             Assert.IsTrue(al.Count == 5);
    117             Assert.IsNotNull(al[0]);
    118             Assert.IsNotNull(al[1]);
    119             Assert.IsNotNull(al[2]);
    120             Assert.IsNotNull(al[3]);
    121             Assert.IsNotNull(al[4]);
    122 
    123             pub = new Publish();
    124             pub.PublishData = "2";
    125             pub.PublishTag = "t1";
    126             al.Clear();
    127             foreach (object item in pbc.Publish(pub))
    128             {
    129                 al.Add(item);
    130             }
    131             Assert.IsTrue(al.Count == 5);
    132             Assert.IsNotNull(al[0]);
    133             Assert.IsNotNull(al[1]);
    134             Assert.IsNotNull(al[2]);
    135             Assert.IsNotNull(al[3]);
    136             Assert.IsNotNull(al[4]);
    137         }
    138 
    139         //测试重名订阅事件
    140         [TestMethod]
    141         public void TestSameNameSubscribe()
    142         {
    143             PubSubCenter pbc = new PubSubCenter();
    144             pbc.AddSubscribe("t1", Test2, "2");
    145             pbc.AddSubscribe("t1", Test2, "2");
    146             pbc.AddSubscribe("t1", Test2, "3");
    147             List<string> al = new List<string>();
    148             foreach (string item in pbc.Publish("t1", "123"))
    149             {
    150                 al.Add(item);
    151             }
    152             Assert.IsTrue(al.Count == 2);
    153             Assert.IsTrue(al[0] == "123");
    154             Assert.IsTrue(al[1] == "123");
    155         }
    156 
    157         //测试多方法订阅单事件
    158         [TestMethod]
    159         public void TestMoreSubscribeToOnePublish()
    160         {
    161             PubSubCenter pbc = new PubSubCenter();
    162             pbc.AddSubscribe("t1", Test2, "1");
    163             pbc.AddSubscribe("t1", Test3, "2");
    164             pbc.AddSubscribe("t1", Test4, "3");
    165             List<string> al = new List<string>();
    166             foreach (string item in pbc.Publish("t1", "2"))
    167             {
    168                 al.Add(item);
    169             }
    170             Assert.IsTrue(al.Count == 3);
    171             Assert.IsTrue(al[0] == "2");
    172             Assert.IsTrue(al[1] == "2");
    173             Assert.IsTrue(al[2] == "2");
    174         }
    175 
    176         //测试单方法订阅多事件
    177         [TestMethod]
    178         public void TestOneSubscribeToMorePublish()
    179         {
    180             PubSubCenter pbc = new PubSubCenter();
    181             pbc.AddSubscribe("t1", Test1, "2", "t1");
    182             pbc.AddSubscribe("t2", Test1, "3", "t2");
    183             pbc.AddSubscribe("t3", Test1, "4", "t3");
    184             pbc.AddSubscribe("t4", Test1, "5", "t4");
    185             IList<String> al = new List<String>();
    186             foreach(String item in pbc.Publish("t1","2"))
    187             {
    188                 al.Add(item);
    189             }
    190             Assert.IsTrue(al.Count == 1);
    191             Assert.IsTrue(al[0] == "2");
    192             al.Clear();
    193             foreach (String item in pbc.Publish("t2", "3"))
    194             {
    195                 al.Add(item);
    196             }
    197             Assert.IsTrue(al.Count == 1);
    198             Assert.IsTrue(al[0] == "3");
    199             al.Clear();
    200             foreach (String item in pbc.Publish("t3", "4"))
    201             {
    202                 al.Add(item);
    203             }
    204             Assert.IsTrue(al.Count == 1);
    205             Assert.IsTrue(al[0] == "4");
    206             al.Clear();
    207             foreach (String item in pbc.Publish("t4", "5"))
    208             {
    209                 al.Add(item);
    210             }
    211             Assert.IsTrue(al.Count == 1);
    212             Assert.IsTrue(al[0] == "5");
    213         }
    214     }
    215 }
  • 相关阅读:
    搭建GitLab+Jenkins持续集成环境图文教程
    Linux学习教程,Linux入门教程(超详细)
    Python基础教程,Python入门教程(非常详细)
    我的Dojo中有一个Mojo(如何编写Maven插件)
    Nginx与安全有关的几个配置
    Tomcat安全设置
    MFC 重绘CButton 支持透明背景的png
    Qt中 QTreeView、QTableView单元项进行重命名
    C++将int与size_t进行比较的陷阱
    C++ using的用法
  • 原文地址:https://www.cnblogs.com/yaozhenfa/p/cshap_publishsubscribe.html
Copyright © 2011-2022 走看看