大概看了下C#官方提供的IObservable接口以及IObserver接口来实现发布和订阅,写的很标准,很有代表性,做下笔记,以后要是项目需要用到发布订阅再基于自己的需求改:

public class BaggageInfo
{
private int flightNo;
private string origin;
private int location; internal BaggageInfo(int flight, string from, int carousel)
{
this.flightNo = flight;
this.origin = from;
this.location = carousel;
} public int FlightNumber {
get { return this.flightNo; }
} public string From {
get { return this.origin; }
} public int Carousel {
get { return this.location; }
}
} ///
/// 发布者
///
public class BaggageHandler : IObservable<BaggageInfo>
{
private List<IObserver<BaggageInfo>> observers;
private List<BaggageInfo> flights; public BaggageHandler()
{
observers = new List<IObserver<BaggageInfo>>();
flights = new List<BaggageInfo>();
} public IDisposable Subscribe(IObserver<BaggageInfo> observer)
{
// Check whether observer is already registered. If not, add it
if (! observers.Contains(observer)) {
observers.Add(observer);
// Provide observer with existing data.
foreach (var item in flights)
observer.OnNext(item);
}
return new Unsubscriber<BaggageInfo>(observers, observer);
} // Called to indicate all baggage is now unloaded.
public void BaggageStatus(int flightNo)
{
BaggageStatus(flightNo, String.Empty, );
} public void BaggageStatus(int flightNo, string from, int carousel)
{
var info = new BaggageInfo(flightNo, from, carousel); // Carousel is assigned, so add new info object to list.
if (carousel > && ! flights.Contains(info)) {
flights.Add(info);
foreach (var observer in observers)
observer.OnNext(info);
}
else if (carousel == ) {
// Baggage claim for flight is done
var flightsToRemove = new List<BaggageInfo>();
foreach (var flight in flights) {
if (info.FlightNumber == flight.FlightNumber) {
flightsToRemove.Add(flight);
foreach (var observer in observers)
observer.OnNext(info);
}
}
foreach (var flightToRemove in flightsToRemove)
flights.Remove(flightToRemove); flightsToRemove.Clear();
}
} public void LastBaggageClaimed()
{
foreach (var observer in observers)
observer.OnCompleted(); observers.Clear();
}
}
internal class Unsubscriber<BaggageInfo> : IDisposable
{
private List<IObserver<BaggageInfo>> _observers;
private IObserver<BaggageInfo> _observer; internal Unsubscriber(List<IObserver<BaggageInfo>> observers, IObserver<BaggageInfo> observer)
{
this._observers = observers;
this._observer = observer;
} public void Dispose()
{
if (_observers.Contains(_observer))
_observers.Remove(_observer);
}
} ///
/// 订阅者
///
public class ArrivalsMonitor : IObserver<BaggageInfo>
{
private string name;
private List<string> flightInfos = new List<string>();
private IDisposable cancellation;
private string fmt = "{0,-20} {1,5} {2, 3}"; public ArrivalsMonitor(string name)
{
if (String.IsNullOrEmpty(name))
throw new ArgumentNullException("The observer must be assigned a name."); this.name = name;
} public virtual void Subscribe(BaggageHandler provider)
{
cancellation = provider.Subscribe(this);
} public virtual void Unsubscribe()
{
cancellation.Dispose();
flightInfos.Clear();
} public virtual void OnCompleted()
{
flightInfos.Clear();
} // No implementation needed: Method is not called by the BaggageHandler class.
public virtual void OnError(Exception e)
{
// No implementation.
} // Update information.
public virtual void OnNext(BaggageInfo info)
{
bool updated = false; // Flight has unloaded its baggage; remove from the monitor.
if (info.Carousel == ) {
var flightsToRemove = new List<string>();
string flightNo = String.Format("{0,5}", info.FlightNumber); foreach (var flightInfo in flightInfos) {
if (flightInfo.Substring(, ).Equals(flightNo)) {
flightsToRemove.Add(flightInfo);
updated = true;
}
}
foreach (var flightToRemove in flightsToRemove)
flightInfos.Remove(flightToRemove); flightsToRemove.Clear();
}
else {
// Add flight if it does not exist in the collection.
string flightInfo = String.Format(fmt, info.From, info.FlightNumber, info.Carousel);
if (! flightInfos.Contains(flightInfo)) {
flightInfos.Add(flightInfo);
updated = true;
}
}
if (updated) {
flightInfos.Sort();
Console.WriteLine("Arrivals information from {0}", this.name);
foreach (var flightInfo in flightInfos)
Console.WriteLine(flightInfo); Console.WriteLine();
}
}
}
using System;
using System.Collections.Generic; public class Example
{
public static void Main()
{
//发布者
BaggageHandler provider = new BaggageHandler();
// 订阅者
ArrivalsMonitor observer1 = new ArrivalsMonitor("BaggageClaimMonitor1");
// 订阅者
ArrivalsMonitor observer2 = new ArrivalsMonitor("SecurityExit");
// 发布
provider.BaggageStatus(, "Detroit", );
//订阅
observer1.Subscribe(provider); provider.BaggageStatus(, "Kalamazoo", );
provider.BaggageStatus(, "New York-Kennedy", );
provider.BaggageStatus(, "Detroit", );
observer2.Subscribe(provider); provider.BaggageStatus(, "San Francisco", );
provider.BaggageStatus();
observer2.Unsubscribe(); provider.BaggageStatus();
provider.LastBaggageClaimed();
}
}

C#订阅与发布标准实现的更多相关文章

  1. Python写ROS 订阅与发布程序

    1. 编写talker代码 vim ..../src/talker.py #!/usr/bin/env python # license removed for brevity import rosp ...

  2. vue - Vue脚手架/消息订阅与发布

    今天的内容有意思了,朋友们继续对我们之前的案例完善,是这样的我们之前是不是靠props来完成父给子,子给父之间传数据,其实父给子最好的方法就是props但是自给父就不是了,并且今天学下来,不仅如此,组 ...

  3. VB.net Wcf事件广播(订阅、发布)

    这篇东西原写在csdn.net上,最近新开通了博客想把零散在各处的都转移到一处.   一.源起 学WCF有一段时间了,可是无论是微软的WebCast还是其他网上的教程,亦或我购买的几本书中,都没有怎么 ...

  4. Replication的犄角旮旯(八)-- 订阅与发布异构的问题

    <Replication的犄角旮旯>系列导读 Replication的犄角旮旯(一)--变更订阅端表名的应用场景 Replication的犄角旮旯(二)--寻找订阅端丢失的记录 Repli ...

  5. SQL Server 复制 订阅与发布

    SQL Server 复制 订阅与发布 通过SQL Server 2008数据库复制实现数据库同步备份 SqlServer2008 数据库同步的两种方式(Sql JOB) SqlServer2008 ...

  6. 利用redis的订阅和发布来实现实时监控的一个DEMO(Python版本)

    redis的list类型有个很好的特性,就是每次添加元素后会返回当前list的长度,利用这个特点,我们可以监控它的长度,比如我们的key是用户注册的IP地址,list中存放的是已经在此IP地址上注册的 ...

  7. redis 订阅与发布

    PUBLISH,SUBSCRIBE,等命令实现订阅与发布 订阅/发布到频道 订阅/发布到模式   频道的订阅与信息发送   订阅subscribe,可以让客户端订阅任意数量的频道, 每当有新信息发送到 ...

  8. Redis订阅和发布模式和Redis事务

    -------------------Redis订阅和发布模式------------------- 1.概念     Redis 发布订阅(pub/sub)是一种消息通信模式:     发送者(pu ...

  9. 实现一个简单的订阅与发布模式的代码块,和redux

    /** * Created by Mrzou on 2018/3/11. */ //实现简单的订阅与发布模式的代码块export function pattern() { let currentLis ...

随机推荐

  1. django restframework permission

    与 authentication 和 throttling 一起,permission 决定是应该接受还是拒绝访问请求.权限检查总是在视图的最开始处运行,在任何其他代码被允许进行之前.权限检查通常会使 ...

  2. SQL---mysql新增字段

    ) DEFAULT NULL COMMENT '姓名' 修改表 people  增加字段 name    长度100  默认为null   备注:姓名

  3. vue学习笔记(三)- vue2.x引入Element-ui

    webpack+vue2.x+element-ui 作者:狐狸家的鱼 本文链接:vue2.x引入Element-ui GitHub:sueRimn 1.新建项目 vue init webpack vu ...

  4. 【洛谷P2822 组合数问题】

    题目连接 #include<iostream> #include<cstring> #include<cstdio> #include<cctype> ...

  5. Fiddler--Composer

    Composer选项卡支持手动构建和发请求:也可以在Session列表中拖拽Session放到Composer中,把该Session的请求复制到用户界面: 点击"execute"按 ...

  6. spark JAVA 开发环境搭建及远程调试

    spark JAVA 开发环境搭建及远程调试 以后要在项目中使用Spark 用户昵称文本做一下聚类分析,找出一些违规的昵称信息.以前折腾过Hadoop,于是看了下Spark官网的文档以及 github ...

  7. [再寄小读者之数学篇](2014-06-22 不等式 [中国科学技术大学2011年高等数学B考研试题])

    证明不等式: $$\bex 1+x\ln\sex{x+\sqrt{1+x^2}}>\sqrt{1+x^2},\quad x>0. \eex$$ 证明: 令 $x=\tan t,\ 0< ...

  8. Android Studio生成签名文件,自动签名,以及获取SHA1和MD5值

    转载请标明出处:http://blog.csdn.net/donkor_/article/details/53487133 前言: 作为谷歌在2013年为开发者提供的IDE环境工具Android St ...

  9. UOJ #311「UNR #2」积劳成疾

    需要锻炼$ DP$能力 UOJ #311 题意 等概率产生一个长度为$ n$且每个数在[1,n]间随机的数列 定义其价值为所有长度为$ k$的连续子数列的最大值的乘积 给定$ n,k$求所有合法数列的 ...

  10. 记录一次Python下Tensorflow安装过程,1.7带GPU加速版本

    最近由于论文需要,急需搭建Tensorflow环境,16年底当时Tensorflow版本号还没有过1,我曾按照手册搭建过CPU版本.目前,1.7算是比较新的版本了(也可以从源码编译1.8版本的Tens ...