首先给出项目的结构

IPublish.cs的源码:

 namespace NsWebChat.PublishSubscribe
{
/// <summary>
/// 发布事件基础接口
/// </summary>
public interface IPublish
{
string PublishTag { get; set; }
object PublishData { get; set; }
}
}

IPubSubCenter.cs的源码:

 namespace NsWebChat.PublishSubscribe
{
/// <summary>
/// 订阅发布中心基础接口
/// </summary>
public interface IPubSubCenter
{
/// <summary>
/// 订阅事件
/// </summary>
bool AddSubscribe(string tag, Func<ISubscribe, object, object> method, object data, string name);
bool AddSubscribe(string tag, Func<ISubscribe, object, object> method, string name);
bool AddSubscribe(Subscribe subscribe);
/// <summary>
/// 获得指定事件的订阅列表
/// </summary>
SubscribeList GetSubscribeList(string tag);
/// <summary>
/// 获得订阅
/// </summary>
Subscribe GetSubscribe(string tag, string name);
/// <summary>
/// 删除订阅
/// </summary>
void RemoveSubscribe(string tag, string name); /// <summary>
/// 发布事件
/// </summary>
IEnumerable<Object> Publish(string tag, object data);
IEnumerable<Object> Publish(string tag);
IEnumerable<Object> Publish(Publish publish);
}
}

ISubscribe.cs的源码:

 namespace NsWebChat.PublishSubscribe
{
/// <summary>
/// 订阅事件基础接口
/// </summary>
public interface ISubscribe
{
/// <summary>
/// 订阅的事件
/// </summary>
string SubscribeTag { get; set; }
/// <summary>
/// 订阅的名称
/// </summary>
string SubscribeName { get; set; }
/// <summary>
/// 响应发布时传递的参数
/// </summary>
object Data { get; set; }
/// <summary>
/// 响应发布的方法
/// </summary>
Func<ISubscribe, object, object> SubscribeMethod { get; set; }
/// <summary>
/// 调用订阅方法
/// </summary>
object Invoke(object val);
}
}

Publish.cs的源码:

 namespace NsWebChat.PublishSubscribe
{
/// <summary>
/// 发布事件基类
/// </summary>
public class Publish : IPublish
{
private string _publishTag;
private object _publishData; public Publish()
{
} public Publish(string tag)
: this(tag, new object())
{ } public Publish(string tag, object val)
{
_publishTag = tag;
_publishData = val;
} public string PublishTag
{
get
{
return _publishTag;
}
set
{
_publishTag = value;
}
} public object PublishData
{
get
{
return _publishData;
}
set
{
_publishData = value;
}
}
}
}

PubSubCenter.cs的源码:

 namespace NsWebChat.PublishSubscribe
{
/// <summary>
/// 订阅发布中心基类
/// </summary>
public class PubSubCenter : IPubSubCenter {
private Dictionary<string, SubscribeList> _pubsubList = new Dictionary<string, SubscribeList>(); public bool AddSubscribe(string tag, Func<ISubscribe, object, object> method, object data ,string name)
{
Subscribe subscribe = new Subscribe();
subscribe.Data = data;
subscribe.SubscribeMethod = method;
subscribe.SubscribeTag = tag;
subscribe.SubscribeName = name;
return AddSubscribe(subscribe);
} public bool AddSubscribe(string tag, Func<ISubscribe, object, object> method, string name)
{
return AddSubscribe(tag, method, new object(),name);
} public bool AddSubscribe(Subscribe subscribe)
{
if (subscribe == null)
{
return false;
}
else
{
if (String.IsNullOrEmpty(subscribe.SubscribeName))
{
return false;
}
Subscribe subscribet = GetSubscribe(subscribe.SubscribeTag, subscribe.SubscribeName);
if (subscribet != null)
{
return false;
}
else
{
if (_pubsubList.ContainsKey(subscribe.SubscribeTag))
{
_pubsubList[subscribe.SubscribeTag].Add(subscribe);
}
else
{
SubscribeList list = new SubscribeList();
list.Add(subscribe);
_pubsubList.Add(subscribe.SubscribeTag, list);
}
return true;
}
}
} public SubscribeList GetSubscribeList(string tag)
{
if (_pubsubList.ContainsKey(tag))
{
return _pubsubList[tag];
}
else
{
return new SubscribeList();
}
} public Subscribe GetSubscribe(string tag, string name)
{
if (_pubsubList.ContainsKey(tag))
{
foreach (Subscribe item in _pubsubList[tag])
{
if (item.SubscribeName == name)
{
return item;
}
}
return null;
}
else
{
return null;
}
} public void RemoveSubscribe(string tag, string name)
{
Subscribe subscribe = GetSubscribe(tag, name);
_pubsubList[tag].Remove(subscribe);
} public IEnumerable<object> Publish(string tag, object data)
{
if (_pubsubList.ContainsKey(tag))
{
foreach (Subscribe item in _pubsubList[tag])
{
yield return item.Invoke(data);
}
}
else
{
yield break;
}
} public IEnumerable<object> Publish(string tag)
{
return Publish(tag, new object());
} public IEnumerable<object> Publish(Publish publish)
{
return Publish(publish.PublishTag, publish.PublishData);
}
}
}

Subscribe.cs源码:

 namespace NsWebChat.PublishSubscribe
{
/// <summary>
/// 订阅事件基类
/// </summary>
public class Subscribe : ISubscribe
{
private object _data;
private Func<ISubscribe, object, object> _subscribeMethod;
private string _subscribeTag;
private string _subscribeName; public Subscribe()
{
} public Subscribe(string tag, Func<ISubscribe, object, object> method)
: this(tag, method, "")
{ } public Subscribe(string tag, Func<ISubscribe, object, object> method, object data)
: this(tag, method, data, "")
{ } public Subscribe(string tag, Func<ISubscribe, object, object> method,string name)
: this(tag, method, new object(), name)
{ } public Subscribe(string tag, Func<ISubscribe, object, object> method, object data,string name)
{
_data = data;
_subscribeTag = tag;
_subscribeMethod = method;
_subscribeName = name;
} public object Data
{
get
{
return _data;
}
set
{
_data = value;
}
} public Func<ISubscribe, object, object> SubscribeMethod
{
get
{
return _subscribeMethod;
}
set
{
_subscribeMethod = value;
}
} public object Invoke(object val)
{
return SubscribeMethod(this, val);
} public string SubscribeTag
{
get
{
return _subscribeTag;
}
set
{
_subscribeTag = value;
}
} public string SubscribeName
{
get
{
return _subscribeName;
}
set
{
_subscribeName = value;
}
}
}
}

SubscribeList.cs的源码:

 namespace NsWebChat.PublishSubscribe
{
/// <summary>
/// 订阅列表
/// </summary>
public class SubscribeList : IList<Subscribe>
{
private List<Subscribe> subscribes = new List<Subscribe>(); public int IndexOf(Subscribe item)
{
return subscribes.IndexOf(item);
} public void Insert(int index, Subscribe item)
{
subscribes.Insert(index, item);
} public void RemoveAt(int index)
{
subscribes.RemoveAt(index);
} public Subscribe this[int index]
{
get
{
return subscribes[index];
}
set
{
subscribes[index] = value;
}
} public void Add(Subscribe item)
{
subscribes.Add(item);
} public void Clear()
{
subscribes.Clear();
} public bool Contains(Subscribe item)
{
return subscribes.Contains(item);
} public void CopyTo(Subscribe[] array, int arrayIndex)
{
subscribes.CopyTo(array, arrayIndex);
} public int Count
{
get
{
return subscribes.Count;
}
} public bool IsReadOnly
{
get { return false; }
} public bool Remove(Subscribe item)
{
return subscribes.Remove(item);
} public IEnumerator<Subscribe> GetEnumerator()
{
return subscribes.GetEnumerator();
} System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return subscribes.GetEnumerator();
}
}
}

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

 namespace WebChatUnitTest
{
[TestClass]
public class PubSubCenterTest
{
public object Test1(ISubscribe subscribe, object data)
{
Assert.IsTrue(subscribe.Data == data);
return data;
} public object Test2(ISubscribe s, object d)
{
return d;
} public object Test3(ISubscribe s, object d)
{
return d;
} public object Test4(ISubscribe s, object d)
{
return d;
} public object Test5(ISubscribe s, object d)
{
return s.SubscribeName;
} //测试删除订阅
[TestMethod]
public void TestRemoveSubscribe()
{
PubSubCenter pbc = new PubSubCenter();
pbc.AddSubscribe("t1", Test5, "");
pbc.AddSubscribe("t1", Test5, "");
pbc.RemoveSubscribe("t1", "");
List<string> al = new List<string>();
foreach (string item in pbc.Publish("t1"))
{
al.Add(item);
}
Assert.IsTrue(al.Count == );
Assert.IsTrue(al[] == "");
pbc.AddSubscribe("t1", Test5, "");
pbc.RemoveSubscribe("t1", "");
al.Clear();
foreach (string item in pbc.Publish("t1"))
{
al.Add(item);
}
Assert.IsTrue(al.Count == );
Assert.IsTrue(al[] == "");
} //测试重载版本的订阅发布
[TestMethod]
public void TestMoreSubscribeAndPublish()
{
PubSubCenter pbc = new PubSubCenter();
Subscribe subscribe = new Subscribe("t1", Test2, "", "");
Subscribe subscribe2 = new Subscribe("t1", Test2, "");
Subscribe subscribe3 = new Subscribe();
subscribe3.SubscribeMethod = Test2;
subscribe3.SubscribeName = "";
subscribe3.SubscribeTag = "t1";
pbc.AddSubscribe(subscribe);
pbc.AddSubscribe(subscribe2);
pbc.AddSubscribe(subscribe3);
pbc.AddSubscribe("t1", Test2, "");
pbc.AddSubscribe("t1", Test2, "", "");
List<object> al = new List<object>();
foreach (object item in pbc.Publish("t1"))
{
al.Add(item);
}
Assert.IsTrue(al.Count == );
Assert.IsNotNull(al[]);
Assert.IsNotNull(al[]);
Assert.IsNotNull(al[]);
Assert.IsNotNull(al[]);
Assert.IsNotNull(al[]);
al.Clear();
foreach (object item in pbc.Publish("t1",""))
{
al.Add(item);
}
Assert.IsTrue(al.Count == );
Assert.IsNotNull(al[]);
Assert.IsNotNull(al[]);
Assert.IsNotNull(al[]);
Assert.IsNotNull(al[]);
Assert.IsNotNull(al[]); Publish pub = new Publish("t1");
al.Clear();
foreach (object item in pbc.Publish(pub))
{
al.Add(item);
}
Assert.IsTrue(al.Count == );
Assert.IsNotNull(al[]);
Assert.IsNotNull(al[]);
Assert.IsNotNull(al[]);
Assert.IsNotNull(al[]);
Assert.IsNotNull(al[]); pub = new Publish("t1", "");
al.Clear();
foreach (object item in pbc.Publish(pub))
{
al.Add(item);
}
Assert.IsTrue(al.Count == );
Assert.IsNotNull(al[]);
Assert.IsNotNull(al[]);
Assert.IsNotNull(al[]);
Assert.IsNotNull(al[]);
Assert.IsNotNull(al[]); pub = new Publish();
pub.PublishData = "";
pub.PublishTag = "t1";
al.Clear();
foreach (object item in pbc.Publish(pub))
{
al.Add(item);
}
Assert.IsTrue(al.Count == );
Assert.IsNotNull(al[]);
Assert.IsNotNull(al[]);
Assert.IsNotNull(al[]);
Assert.IsNotNull(al[]);
Assert.IsNotNull(al[]);
} //测试重名订阅事件
[TestMethod]
public void TestSameNameSubscribe()
{
PubSubCenter pbc = new PubSubCenter();
pbc.AddSubscribe("t1", Test2, "");
pbc.AddSubscribe("t1", Test2, "");
pbc.AddSubscribe("t1", Test2, "");
List<string> al = new List<string>();
foreach (string item in pbc.Publish("t1", ""))
{
al.Add(item);
}
Assert.IsTrue(al.Count == );
Assert.IsTrue(al[] == "");
Assert.IsTrue(al[] == "");
} //测试多方法订阅单事件
[TestMethod]
public void TestMoreSubscribeToOnePublish()
{
PubSubCenter pbc = new PubSubCenter();
pbc.AddSubscribe("t1", Test2, "");
pbc.AddSubscribe("t1", Test3, "");
pbc.AddSubscribe("t1", Test4, "");
List<string> al = new List<string>();
foreach (string item in pbc.Publish("t1", ""))
{
al.Add(item);
}
Assert.IsTrue(al.Count == );
Assert.IsTrue(al[] == "");
Assert.IsTrue(al[] == "");
Assert.IsTrue(al[] == "");
} //测试单方法订阅多事件
[TestMethod]
public void TestOneSubscribeToMorePublish()
{
PubSubCenter pbc = new PubSubCenter();
pbc.AddSubscribe("t1", Test1, "", "t1");
pbc.AddSubscribe("t2", Test1, "", "t2");
pbc.AddSubscribe("t3", Test1, "", "t3");
pbc.AddSubscribe("t4", Test1, "", "t4");
IList<String> al = new List<String>();
foreach(String item in pbc.Publish("t1",""))
{
al.Add(item);
}
Assert.IsTrue(al.Count == );
Assert.IsTrue(al[] == "");
al.Clear();
foreach (String item in pbc.Publish("t2", ""))
{
al.Add(item);
}
Assert.IsTrue(al.Count == );
Assert.IsTrue(al[] == "");
al.Clear();
foreach (String item in pbc.Publish("t3", ""))
{
al.Add(item);
}
Assert.IsTrue(al.Count == );
Assert.IsTrue(al[] == "");
al.Clear();
foreach (String item in pbc.Publish("t4", ""))
{
al.Add(item);
}
Assert.IsTrue(al.Count == );
Assert.IsTrue(al[] == "");
}
}
}

C#实现发布订阅模式的更多相关文章

  1. 15天玩转redis —— 第九篇 发布/订阅模式

    本系列已经过半了,这一篇我们来看看redis好玩的发布订阅模式,其实在很多的MQ产品中都存在这样的一个模式,我们常听到的一个例子 就是邮件订阅的场景,什么意思呢,也就是说100个人订阅了你的博客,如果 ...

  2. 第五章 --- 关于Javascript 设计模式 之 发布-订阅模式

    先来个最简单的 发布订阅模式 document.body.addEventListener('click',function(){ alert(123); }); document.body.clic ...

  3. NetMQ(三): 发布订阅模式 Publisher-Subscriber

    ZeroMQ系列 之NetMQ 一:zeromq简介 二:NetMQ 请求响应模式 Request-Reply 三:NetMQ 发布订阅模式 Publisher-Subscriber 四:NetMQ ...

  4. C# 委托和事件 与 观察者模式(发布-订阅模式)讲解 by天命

    使用面向对象的思想 用c#控制台代码模拟猫抓老鼠 我们先来分析一下猫抓老鼠的过程 1.猫叫了 2.所有老鼠听到叫声,知道是哪只猫来了 3.老鼠们逃跑,边逃边喊:"xx猫来了,快跑啊!我是老鼠 ...

  5. 4.js模式-发布-订阅模式

    1. 发布-订阅模式 var observe = (function(){ var events = {}, listen, trigger, remmove; listen = function(k ...

  6. RabbitMQ/JAVA (发布/订阅模式)

    发布/订阅模式即生产者将消息发送给多个消费者. 下面介绍几个在发布/订阅模式中的关键概念-- 1. Exchanges (转发器) 可能原来我们都是基于一个队列发送和接收消息.现在介绍一下完整的消息传 ...

  7. Javascript中理解发布--订阅模式

    Javascript中理解发布--订阅模式 阅读目录 发布订阅模式介绍 如何实现发布--订阅模式? 发布---订阅模式的代码封装 如何取消订阅事件? 全局--发布订阅对象代码封装 理解模块间通信 回到 ...

  8. ActiveMQ发布订阅模式

    ActiveMQ的另一种模式就SUB/HUB即发布订阅模式,是SUB/hub就是一拖N的USB分线器的意思.意思就是一个来源分到N个出口.还是上节的例子,当一个订单产生后,后台N个系统需要联动,但有一 ...

  9. redis的发布订阅模式

    概要 redis的每个server实例都维护着一个保存服务器状态的redisServer结构 struct redisServer {     /* Pubsub */     // 字典,键为频道, ...

  10. 理解JavaScript设计模式与开发应用中发布-订阅模式的最终版代码

    最近拜读了曾探所著的<JavaScript设计模式与开发应用>一书,在读到发布-订阅模式一章时,作者不仅给出了基本模式的通用版本的发布-订阅模式的代码,最后还做出了扩展,给该模式增加了离线 ...

随机推荐

  1. [Android Security] 反编译常用工具

    copy : https://down.52pojie.cn/Tools/Disassemblers/

  2. JUnit4单元测试入门教程

    本文按以下顺序讲解JUnit4的使用 下载jar包 单元测试初体验 自动生成测试类 执行顺序 @Test的属性 下载jar包## 下载地址 在github上,把以下两个jar包都下载下来.     下 ...

  3. 连接MSSQL2008 Express

    (1)打开Manage Studio. (2)click on the  .\sqlexpress, select property, click security, make sure use mi ...

  4. Netty Associated -- ByteBuf

    ByteBuf ByteBuf是Netty的Server与Client之间通信的数据传输载体.他提供了一个byte数组(byte[])的抽象视图 buffer创建 我们推荐通过一个Unpooled的帮 ...

  5. [leetcode]Substring with Concatenation of All Words @ Python

    原题地址:https://oj.leetcode.com/problems/substring-with-concatenation-of-all-words/ 题意: You are given a ...

  6. UML图与软件开发过程那点关系

    首先,软工文档, 软工文档,也就是计划,设计,描述,使用软件的一些文件,它最大的特点就是固定不变,用来给不同的人和计算机来阅读.在期间,文档起到了桥梁的作用,看这张图很形象: 在这里在看一下国家统一规 ...

  7. Mac-OSX下Ruby更新

    Mac下是自带Ruby环境的,在有些情况我们是需要更新Ruby的,安装和更新Ruby环境可以通过rvm命令进行操作,rvm在安装过程中通过HomeBrew安装依赖包,如果之前没有装过HomeBrew, ...

  8. 程序员训练机器学习 SVM算法分享

    http://www.csdn.net/article/2012-12-28/2813275-Support-Vector-Machine 摘要:支持向量机(SVM)已经成为一种非常受欢迎的算法.本文 ...

  9. StackPanel

    StackPanel 的 HorizontalAlignment 属性和 VerticalAlignment 属性 默认情况下,这两个属性都被设置为 Stretch.

  10. 强化Linux安全的10个技能

    1.找出不必要的服务 很明显,服务器上跑的服务,并不是每个都有用的.强烈建议检查并关掉不需要的服务,从而减少风险(多跑一个服务,就可能多几个漏洞). 查询运行在runlevel 3的服务列表: [af ...