大概看了下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. virtualbox虚拟机使用的是桥接网络无法连接外网

    virtualbox虚拟机使用的是桥接网络,获取到的DHCP,无法和外界通信 查看路由表发现有两个默认路由,优先级高的路由指向了,仅主机网络的网关 删除第一个默认路由

  2. 【WC2018】即时战略

    题目描述 小M在玩一个即时战略(Real Time Strategy)游戏.不同于大多数同类游戏,这个游戏的地图是树形的. 也就是说,地图可以用一个由 n个结点,n?1条边构成的连通图来表示.这些结点 ...

  3. CentOS7使用firewalld防火墙配置端口

    安装启用firewalld防火墙 CentOS7默认的防火墙是firewalld 如果没有firewalld防火墙,可以执行yum install firewalld 命令进行安装 firewalld ...

  4. Mybatis的应用1 Mybatis和logback的应用配置

    首先新建一个module, 然后,在pom文件里面添加一些引用的项. pom.xml <?xml version="1.0" encoding="UTF-8&quo ...

  5. python httpserver

    python3: python -m http.server 80 python2: python -m SimpleHTTPServer 9004

  6. mybatis查询语句获取自增主键

    第一种方式: 主键回填useGeneratedKeys 代表采用JDBC的Statment对象的getGeneratedKeys方法返回主键keyProperty 代表将用哪个POJO的属性去匹配这个 ...

  7. C# - Visual Studio简明操作

    Visual Studio简明操作 安装Northwind示例数据库 运行安装程序,结束安装后,再CMD中输入以下命令 cd C:\SQL Server  Sample Databases(回车) s ...

  8. vue父子组件之间互相获取data值&调用方法(非props)

    vue 子组件调用父组件方法&数据 vue有$parent这么一个属性,在子组件中就能拿到父组件的数据 this.$parent.xxx 就能调用父组件的方法 this.$parent.xxx ...

  9. 对OAuth协议的认识

    一. OAuth是什么 OAuth 是Open Authorization的简写.OAuth 协议为用户资源的授权提供了一个安全的.开放而又简易的标准. 通俗地说,就是当我们想把自己系统的某些功能暴露 ...

  10. java应用的优化【转】

    XX银行网银系统是一套全新的对公业务渠道类系统,经过两年的建设,将逐步对外提供服务. 该系统融合了原来多个对公渠道系统,并发量是以前多个系统之和,吞吐量要求将大幅上升.为了使广大对公客户使用系统时获得 ...