响应式扩展还带来了一组丰富的操作符。在Rx中,使用运算符进行操作是一种不错的方式,但同时它也是领域特定语言的一部分(DSL),它以声明的方式描述事件处理。Rx运算符允许获取可观察对象和观察者,并创建查询、转换、投影和其他您可能从LINQ中了解到的事件处理器的管道。Rx库还包括基于时间的操作和特定于rx的操作,用于查询、同步、错误处理等。
例如,这就是您订阅可观察字符串序列的方式,该序列将仅显示以A开头的字符串,并将其转换为大写:
IObservable<string> strings= ... //字符串的可观察对象,它将字符串推入观察者
IDisposable subscription = //保存订阅使您可以稍后取消订阅。
strings.Where(str => str.StartsWith("A")) //只允许以A开头的字符串传递给观察者
.Select(str => str.ToUpper()) //字符串在继续之前被转换为大写。
.Subscribe(...); //观察者被订阅以接收通过过滤和转换的字符串。
subscription.Dispose(); //当不再希望接收字符串时,解除订阅。
如果你不理解每个关键词的所有语法或含义,不要害怕。我将在下一章中对它们进行解释。
在这个简单的示例中,您可以看到Rx操作符的声明式风格——说明什么你想要的,而不是你想要的——所以代码读起来就像一个故事。因为我想在这个例子中,为了关注查询操作符,我没有展示可观察对象是怎样的创建。您可以通过多种方式创建可观察对象:从事件、枚举、异步类型等等。这些将在第4章和第5章中讨论。现在,您可以假设可观察对象是在幕后为您创建的。
操作符和组合符(组合多个可观察对象的操作符)可以帮助您创建涉及多个可观察对象的更复杂的场景。要实现Shoppy示例中商店的可调整大小的图标,可以编写以下Rx表达式:
IObservable<Store> stores = ... //可观察对象,它传递关于系统中商店的信息
IObservable<Location> myLocation = ...//携带我们当前地理位置信息的可观察对象
IObservable<StoreIconSize> iconSize =
from store in stores //处理每个store并为其分配store变量(该变量的类型为Store,因为stores是Store的一个可观察对象)
from currentLocation in myLocation //类似于可观察到的商店。获取所有商店对和当前位置,每次位置都在变化。
let distance = store.Location.DistanceFrom(currentLocation)
let size = (MINIMAL_RADIUS / dist) * MIN_ICON_SIZE
select new StoreIconSize { Store=store , Size=size }; //允许您为每对存储和位置创建一个新变量。以这种方式创建两个变量来计算与商店的距离,然后计算商店图标的大小。
iconSize.Subscribe( iconInfo => iconInfo.Store.Icon = iconInfo.Size);//lambda表达式充当观察者的OnNext实现,每次商店图标有新的大小时都会被调用。
即使不了解响应式扩展的所有细节,您也可以看到在Shoppy应用程序中实现此功能所需的代码量很小,而且很容易读懂。所有结合各种数据流的样板都是由Rx完成,省去了编写所需的独立代码片段的负担处理数据变更事件。
——未完待续
译者:重庆教主 2024.05.14
网站:WPF中文网 wpfsoft.com