C#订阅与发布标准实现
大概看了下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#订阅与发布标准实现的更多相关文章
- Python写ROS 订阅与发布程序
1. 编写talker代码 vim ..../src/talker.py #!/usr/bin/env python # license removed for brevity import rosp ...
- vue - Vue脚手架/消息订阅与发布
今天的内容有意思了,朋友们继续对我们之前的案例完善,是这样的我们之前是不是靠props来完成父给子,子给父之间传数据,其实父给子最好的方法就是props但是自给父就不是了,并且今天学下来,不仅如此,组 ...
- VB.net Wcf事件广播(订阅、发布)
这篇东西原写在csdn.net上,最近新开通了博客想把零散在各处的都转移到一处. 一.源起 学WCF有一段时间了,可是无论是微软的WebCast还是其他网上的教程,亦或我购买的几本书中,都没有怎么 ...
- Replication的犄角旮旯(八)-- 订阅与发布异构的问题
<Replication的犄角旮旯>系列导读 Replication的犄角旮旯(一)--变更订阅端表名的应用场景 Replication的犄角旮旯(二)--寻找订阅端丢失的记录 Repli ...
- SQL Server 复制 订阅与发布
SQL Server 复制 订阅与发布 通过SQL Server 2008数据库复制实现数据库同步备份 SqlServer2008 数据库同步的两种方式(Sql JOB) SqlServer2008 ...
- 利用redis的订阅和发布来实现实时监控的一个DEMO(Python版本)
redis的list类型有个很好的特性,就是每次添加元素后会返回当前list的长度,利用这个特点,我们可以监控它的长度,比如我们的key是用户注册的IP地址,list中存放的是已经在此IP地址上注册的 ...
- redis 订阅与发布
PUBLISH,SUBSCRIBE,等命令实现订阅与发布 订阅/发布到频道 订阅/发布到模式 频道的订阅与信息发送 订阅subscribe,可以让客户端订阅任意数量的频道, 每当有新信息发送到 ...
- Redis订阅和发布模式和Redis事务
-------------------Redis订阅和发布模式------------------- 1.概念 Redis 发布订阅(pub/sub)是一种消息通信模式: 发送者(pu ...
- 实现一个简单的订阅与发布模式的代码块,和redux
/** * Created by Mrzou on 2018/3/11. */ //实现简单的订阅与发布模式的代码块export function pattern() { let currentLis ...
随机推荐
- php+mysql+nginx+liunx 服务搭建
安装php7相应的yum源 CentOS 7.x: # rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7 ...
- (二叉树 递归 DFS) leetcode 100. Same Tree
Given two binary trees, write a function to check if they are the same or not. Two binary trees are ...
- 20175209 《Java程序设计》第五周学习总结
20175209 <Java程序设计>第五周学习总结 一.教材知识点总结 1.接口的定义 接口声明:关键字interface 接口体:public static final 修饰常量,pu ...
- Decision tree(决策树)算法初探
0. 算法概述 决策树(decision tree)是一种基本的分类与回归方法.决策树模型呈树形结构(二分类思想的算法模型往往都是树形结构) 0x1:决策树模型的不同角度理解 在分类问题中,表示基于特 ...
- 2018-2019-2 《Java程序设计》第5周学习总结
20175319 2018-2019-2 <Java程序设计>第5周学习总结 教材学习内容总结 本周学习<Java程序设计>第六章: 接口 实现接口 接口的UML图 接口回调 ...
- 第二十节: 深入理解并发机制以及解决方案(锁机制、EF自有机制、队列模式等)
一. 理解并发机制 1. 什么是并发,并发与多线程有什么关系? ①. 先从广义上来说,或者从实际场景上来说. 高并发通常是海量用户同时访问(比如:12306买票.淘宝的双十一抢购),如果把一个用户看做 ...
- c#管理文件系统
using System; using System.Collections.Generic; using System.IO; using static System.Console; /*Syst ...
- 设计模式十: 生成器模式(Builder Pattern)
简介 生成器模式属于创建型模式的一种, 又叫建造者模式. 生成器模式涉及4个关键角色:产品(Product),抽象生成器(builder),具体生成器(ConcreteBuilder),指挥者(Dir ...
- AGC电路以及AD8347正交解调芯片
1.AGC电路的工作原理 1.1AGC电路的用途 随着电磁环境的日益恶化, 不同频段电磁信号之间的相互串扰, 以及可能出现的人为干扰, 将会导致接收机输入端口的信号动态范围较大, 一旦出现电路饱和或是 ...
- k64 datasheet学习笔记21--Direct Memory Access Multiplexer (DMAMUX)
0.前言 本章主要介绍DMA MUX的相关内容 1.简介 1.1 概述 用来路由DMA源到16路DMA通道: 1.2 特性 1.52个外设slot和10个常开slot可以路由到16路DMA通道 2.1 ...