Materialize and Dematerialize
Timestamp和TimeInterval可以用于日志记录和调试,Materialize操作也一样。Materialize将队列转换为队列的元数据形式,它接受一个IObservable<T>并将其转换为IObservable<Notification<T>>。Notification提供队列事件的元数据。
如果我们Materialize一个队列,可以看到被包裹后的值开始被返回:
Output:
Materialize-->OnNext(1)
Materialize-->OnNext(2)
Materialize-->OnNext(3)
Materialize-->OnCompleted()
Materialize completed
从输出中我们可以看到1、2、3分别被标明了属于哪种消息。
当源队列完成时,materialized队列产生一个OnCompleted消息后完成。Notification<T>是一个具有3个实现的的抽象类
- OnNextNotification
- OnErrorNotification
- OnCompletedNotification
Notification<T>暴露4个公共属性: Kind、HasValue、Value和Exception。显然只有OnNextNotification将为HasValue返回true,并对Value有一个有价值的实现。OnErrorNotification是唯一一个处理错误的实现。Kind属性返回一个枚举,它让你知道适合使用那些方法:
下面的例子中我们将产生一个错误队列,注意,最后的值是一个OnErrorNotification,并且队列不抛出错误,它会成功的完成:
Output:
Materialize-->OnNext(1)
Materialize-->OnNext(2)
Materialize-->OnNext(3)
Materialize-->OnError(System.Exception)
Materialize completed
Materializing可以方便的分析或者log队列。而通过Dematerialize方法可以unwarp一个Materializing队列,Dematerialize方法只对IObservable<Notification<TSource>>起作用。
SelectMany
在Transformation操作中,Select是最有用的,但SelectMany更强大。SelectMany是绑定方法,大多数其他操作可以和SelectMany配合使用。将SelectMany想象为“根据一个(来源)来产生0个或更多元素”可以帮助我们理解它,它的签名如下:
selector参数是一个Func委托,接受一个T类型的单值返回一个队列,返回的队列不必与源类型相同,SelectMany返回的类型为selector的返回类型。
下面这个例子接受一个带有单一值“3”的队列。selector方法将产生进一步的数字。结果队列将是一个从1到3的数字范围,我们接受了一个队列[3],从selector返回队列[1,2,3,](也就是说根据队列中的元素3和selector方法返回了一个新的range队列):
Output:
SelectMany-->1
SelectMany-->2
SelectMany-->3
SelectMany completed
如果把源修改为队列[1,2,3,]:
我们将得到根据每个值产生的range队列(元素1产生队列[1],元素2产生队列 [1,2],元素3产生队列[1,2,3]),并输出:[1(第一个被产生的队列的元素),1,2(第二个被产生的队列的元素),1,2,3(第三个被产生的队列的元素)].
SelectMany-->1
SelectMany-->1
SelectMany-->2
SelectMany-->1
SelectMany-->2
SelectMany-->3
SelectMany completed
下面的例子更好的说明了SelectMany可以接受一个单一值并将其扩展为多个值。当我们将其运用到一个值队列,其结果是每个子队列组合并产生最终队列。前面的例子中我们返回了与源类型相同的队列,但并没有这样的硬性要求,所以下面的例子我们返回不同的类型,将int转换为char,selector方法将返回一个带有单一值的char队列:
这里的1将被转换为“A”:
SelectMany-->A
SelectMany completed
扩展源队列为多个值,将给我们一个有多个值的结果:
输入了[1,2,3],之后产生了 [队列[A], 队列[B], 队列[C]],最后组合为[A,B,C]。
SelectMany-->A
SelectMany-->B
SelectMany-->C
注意,我们已经有效的重建了Select操作。
最后一个例子将数字映射到一个字母。由于只有26个字母,忽略大于26的值是很方便的做法。但我们必须为源的每一个值都返回一个队列,就没有任何规则可以防止出现空队列。这种情况下如果数字大于26将返回空队列:
Output:
A
B
C
...
X
Y
Z
Completed
源队列从1到30,小于26的都产生了对应的字母,到27时selector委托返回了空队列,其后也是一样。一旦selector产生的所有队列被组合起来,我们将得到26个字母的队列。
在Where方法中写SelectMany的例子:
在Select方法中写SelectMany的例子:
大神停更了?突然好久没看见你了!
@Oncle:那啥,我不是大神,萌新哈~本职是3D美术~最近忙实践呢~哈哈,学了很多概念,正在弄一个基于RX的MVVM系统,算是试个手,有点沉迷进去了,于是笔记整理就怠慢了,呵呵~中午我先更新一篇