Rx响应式编程知多少 - 系列:LINQ和Rx简介
Posted dotNET匠人
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Rx响应式编程知多少 - 系列:LINQ和Rx简介相关的知识,希望对你有一定的参考价值。
加个“星标★”,每日 7:15,好文必达!
原文:https://dwz.cn/IYM2e0sF
相信大家都用过Language Integrated Query (LINQ),他是一种强大的工具能够从集合中提取数据。Reactive Extensions(Rx)是对LINQ的一种扩展,他的目标是对异步的集合进行操作,也就是说,集合中的元素是异步填充的,比如说从webservice或者云端获取数据然后对集合进行填充。
LINQ是从C#3.0开始引入的语言特性,而Rx起源于Microsoft DevLabs小组的研究,他扩展了LINQ的一些特性,目前Rx支持多种平台如javascript,Windows Phone。随着数据处理变得复杂,LINQ使得我们的处理逻辑变得简单清晰,同样地,随着越来越多的数据通过从云端异步获取,Rx使得这种异步数据处理操作变得简单和容易维护。
本文简要介绍LINQ和Rx的重要性,并用代码展示了LINQ和Rx的一些基本操作。
1. 什么是LINQ和Rx
1.1 什么是LINQ
LINQ是.NET的一个扩展,专门用来对数据集合,关系数据,XML文件等对象进行查询和提取数据的技术,他提供了统一的类似SQL的语法来对数据进行查询,而不用关心数据源的不同。
LINQ使得我们的代码风格更加声明化和函数化,在我之前的一篇文章 查询表达式和循环控制 读者可以明显的感受到这一点。声明式编程风格相信大家都使用过,比如说C#中的特性(AttributeClass),WPF中的XAML以及F#语言,大家可以从中体会到,声明式编程风格强调的是实现的逻辑和需求,而不是具体的执行步骤。LINQ和Rx是C#中声明式和函数式编码风格的一部分,他强调如何能够完成想要的功能,而不是专注于怎么样去实现。函数式编程(Function Programming)和传统的命令式编程(Imperative Programing)风格相比,代码更加简洁明了,容易维护。
命令是编程中,程序通常有几个步骤组成,在某一步骤中通常有循环,循环体内是具体的逻辑。在声明式编程中,使用更高一层的抽象来表达意图。举例来说,命令式编程式编程通常是这样的"打开所有员工集合,遍历集合中的元素,看该员工是否是经理,如果是,则将工资增加20%,然后将增加后的工资更新回集合中去",而声明式编程风格大体会是"将经理的工资增加20%",可见,命令式编程注重的是如何完成某一任务,生命式编程则注重的是要完成什么任务。
1.2 什么是Rx
Rx提供了一种新的组织和协调异步事件的方式,例如协调多个从云端返回的多个异步的数据流。Rx能够是的我们用一个简单的方式来处理这些数据流,极大的简化了代码的编写。例如,.NET中传统的Begin/End异步编程模式在处理单个异步操作时可以应付,但是如果同时多个异步调用时,线程控制就会使得代码变得比较复杂。使用Rx,Begin/End模式就变成了一条简单的方法,这使得代码更加清晰和容易理解。
Rx最显著的特性是使用可观察集合(Observable Collection)来达到集成异步(composing asynchronous)和基于事件(event-based)的编程的效果。Rx有一些几个特性。
-
组合(Composing): Reactive Extension的首要目标之一就是将多种异步操作组合起来是的代码更加简单。要做到这一点,数据流必须定义清楚,这样代码就很清晰集中,使得异步操作代码异步处理代码不会充斥整个应用程序。 -
异步(Asynchronous): 虽然Rx不仅仅能处理异步操作,但是使用Rx,大大简化了异步操作的实现,并且代码容易理解进而容易维护。 -
基于事件(Event-based): Rx简化了传统的异步编程方式,在后面的文章中我们会看到拖放(drag and drop)模式的实现 -
可观察集合(Observable collections): Obervable Collection是Rx的核心,它是一种集合,集合的元素在第一次访问的时候肯能还没有填充。它对与Rx的重要性类始于enumerable集合对LINQ的重要性。
2. 获取和安装Rx
如果使用.NET 3或者之后的版本,那么LINQ已经集成到framework中了,同样,如果安装了Windows Phone开发工具,Rx的WindowsPhone版本也会自动安装。要获得最新的Rx可以访问其官网(http://msdn.microsoft.com/en-us/data/gg577609)。
3. Rx与LINQ的异同
在处理静态集合数据方面,LINQ使用类似SQL的语法来操作和使用不同来源的数据。相反,Rx被设计出来用来处理将来才会填充好的集合,也就是说,集合类型定义好了,但是集合中的元素可能在未来的某一时刻才会被填充。
在使用LINQ之前要求集合中的所有元素都可以使用,也就是说在使用LINQ集合进行操作时,需要一个初始的静态的集合。但是,问题来了,如果集合中有些数据目前还在处理之中,或者说是调用远处的webservice结果还没有返回,或者是一些实时产生的数据会不断的往集合中添加,那么对于这类集合LINQ不知道该怎么处理,因为他们不是静态的,集合中的元素会在未来的某一个时刻继续添加,并且数据到达的事件不确定。Rx就是针对这种数据集合设置的,它是的操作这类数据集合就像LINQ操作静态数据集合那样简单。
就像大家开始接触LINQ那样会感觉不容易理解,初次接触Rx也会有类似的问题。一旦理解和熟悉了Rx的语法,就会感觉和LINQ一样亲切,一些复杂的异步操作使用Rx可以非常简单的实现。
LINQ和Rx在技术上有很多相似的地方。在LINQ对集合进行一系列操作如添加,移除,修改,提取后,会得到一个新的集合,新集合只是原始集合的一个修改版本。Rx也是一样,咋一看,集合和数据流看起来非常不同,但是他们在很多关键的地方有联系,这就是我们将数据流称之为未来的集合的原因。集合和数据流都是多数据按某种顺序进行排列。LINQ和Rx可以这些序列进行一系列操作然后得到一个新的序列。
使用LINQ和Rx能够带给我们很多好处,他们有以下好处:
-
他们是.NET框架中的一级成员(first-class member)。Visual Studio中完全支持对LINQ和Rx的智能感知和语法高亮。 -
他们能够以一种统一的方式来处理各种数据源产生的数据,这些数据源包括数据库或者XML文件。 -
他们具有很强的扩展性。你可以编写自己的类库来扩展这些框架。 -
组合性。LINQ和Rx都可以将一系列复杂的操作和变化组合到一小片代码段中。使得代码更加简洁。 -
声明式风格。LINQ和Rx为编程带来了一些函数式编程的风格。 -
简化实现。很多时候一条或者几条LINQ,Rx语句就能轻易实现很多需要复杂和晦涩的语句才能完成的功能。
4. Rx和LINQ的简单例子
讲了这么多,下面来看看一个简单的例子来说明LINQ和Rx的用法。大家可能对LINQ比较熟悉,那么先看看LINQ。
static void Main(string[] args)
{
List<Int32> its = Enumerable.Range(1, 15).ToList();
its.Where(i => i % 2 == 0).ToList().ForEach(i => Console.Write("{0} ", i));
Console.ReadKey();
}
上述代码输出结果:2 4 6 8 10 12 14
上面例子很简单,首先使用Enumerable对象的Range方法初始化一个list集合,然后使用LINQ的方法型表达式过滤所有偶数,LINQ语句代码执行返回一个IEnumerable集合,然后使用IEnumerable集合的扩展方法Tolist将其转换为List集合,在调用ForEach方法传入一个匿名方法将所有集合中的所有元素打印出来,整个代码紧凑易读,逻辑清晰。
C:\Program Files\Microsoft Reactive Extensions SDK\v1.0.10621\Binaries.NETFramework\v4.0\ System.Reactive.dll。
static void Main(string[] args)
{
IObservable<Int32> input = Observable.Range(1, 15);
input.Where(i => i % 2 == 0).Subscribe(x => Console.Write("{0} ", x));
Console.ReadKey();
}
代码输出结果和LINQ版本的完全相同,但是程序的内在逻辑完全不同。上述代码中,首先使用Observable对象产生一个IObservable对象集合,然后使用Where子句过滤其中的元素,得到一个新的IObservable对象,然后对对象中的每一个元素注册一个方法,上述代码中使用的是匿名方法将每个元素打印出来。当集合中有元素时,因为元素注册了该方法,所以就会调用该方法把元素打印出来。
LINQ和Rx的能处理的集合类型不同导致其产生内在逻辑不同,下面先简单了解一下Enumerable集合和Observable集合。
5. Enumerable集合和Observable集合
LINQ和Rx都是用来对集合进行操作。LINQ操作的集合实现了IEnumerable借口,能够使用foreach语句遍历集合。而Rx操作的集合实现了IEnumerable,IQueryable集合,这样的集合称之为Observable集合。大家对Enumerable集合可能很熟悉,他是foreach语句的基础,我的另一篇文章对这个有详细介绍,这里就不多说了,下面主要来看看Observable集合。
Rx对Observable集合进行操作,这个集合的命名是从观察者设计模式得来的,观察者模式的基础是委托和事件,所以要了解这一模式需要理解委托和事件,在这里推荐张子阳的文章C#中的委托和事件。Enumebrable集合中所有的元素在集合中都已经填充好了,是静态的,用户可以使用"拉"的方式从集合中遍历元素进行处理。而Observable集合则不同,在创建该集合时,集合中的元素可能会在以后的某个时间才能添加进去。由于集合注册了事件,一旦集合中的元素到达,就会触发这一事件,将信息"推"到注册者哪里去。
现在在Windows Phone中演示如何使用这两个集合,在WindowPhone界面上添加两个ListBox控件,一个使用Enumerable集合填充一个使用Observable集合填充。具体步骤如下:
1. 新建一个Windows Phone项目,在界面上放两个ListBox,分别命名为lblEnumerable和lblObservable。
2. 添加System.Observable.dll和Microsoft.Phone.Reactive.dll,并在代码中添加对Microsoft.Phone.Reactive的引用。
3. 初始化一个数组变量,然后分别利用两种方式分别对这两个ListBox进行填充。
完整代码如下:
using Microsoft.Phone.Controls;
using Microsoft.Phone.Reactive;
namespace IntroductionRxPhoneApp
{
public partial class MainPage : PhoneApplicationPage {
readonly List<String> fruits = new List<string>{
"Apple","Orange","Banana","Pears","melon"};
// 构造函数 public MainPage()
{
InitializeComponent();
PopulateCollection();
}
private void PopulateCollection()
{
//使用Enumerable集合进行填充 fruits.ForEach(fruit => lblEnumerable.Items.Add(fruit));
//使用Observable集合进行填充 IObservable<String> observable = fruits.ToObservable();
observable.Subscribe(fruit => lblObservable.Items.Add(fruit));
}
}
}
运行程序可以看到两个下拉框中的内容是一样的。
6. 结语
本文简要介绍了什么是Rx以及Rx如何对LINQ进行的扩展。并以实际代码简单演示了Rx的用法,希望本文对您了解Rx有所帮助,因为Rx和LINQ有在技术方面有很多共同的地方,所以下一篇文章将会介绍LINQ的一些核心的用法,敬请期待!
End
微信后台回复“ asp”,给你:一份 全网最强的ASP.NET学习路线图。
回复“ cs”,给你:一整套 C# 和 WPF 学习资源!
回复“core”,给你:2019年dotConf大会上发布的.NET core 3.0学习视频!
回复“so”,给你:一套给力的 超级搜索力视频 课程!
朕已阅
以上是关于Rx响应式编程知多少 - 系列:LINQ和Rx简介的主要内容,如果未能解决你的问题,请参考以下文章
理论 | Angular 中的响应式编程 -- 浅淡 Rx 的流式思维