Reactive ExtensionsLINQ和Rx简单介绍
LINQ和Rx简单介绍
相信大家都用过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方法传入一个匿名方法将所有集合中的所有元素打印出来,整个代码紧凑易读,逻辑清晰。
下面来如何使用Rx实现上述功能。要使用Rx必须添加System.Reactive.dll,默认安装路径下,我本机的地址为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的一些核心的用法,敬请期待!
Reactive ExtensionsLINQ和Rx简单介绍的更多相关文章
- Reactive Extensions(Rx)并发浅析
Reactive Extensions(Rx)并发浅析 iSun Design & Code .Net并行编程 - Reactive Extensions(Rx)并发浅析 关于Reactive ...
- .Net并行编程 - Reactive Extensions(Rx)并发浅析
关于Reactive Extensions(Rx) 关于Reactive Extensions(Rx),先来看一下来自微软的官方描述: The Reactive Extensions (Rx) is ...
- 牛刀小试:使用Reactive Extensions(Rx),对短时间内多次发生的事件限流
我之前有一篇文章介绍到了Reactive Extension这个组件,请参考下面的文章,其中有一些基本的概念和相关的链接 牛刀小试:使用Reactive Extensions(Rx),一行代码实现多线 ...
- 使用Reactive Extensions(Rx),对短时间内多次发生的事件限流
使用Reactive Extensions(Rx),对短时间内多次发生的事件限流 牛刀小试:使用Reactive Extensions(Rx),对短时间内多次发生的事件限流 我之前有一篇文章介绍到了R ...
- 第一篇:SpringBoot2.0简单介绍
距离Spring Boot1.0发布已经4年了,今年3月份SpringBoot2.0正式发布.让我们一起来了解一下它. Spring Boot主要依赖于Spring,整合了很多框架的使用方式,帮助开发 ...
- [原创]关于mybatis中一级缓存和二级缓存的简单介绍
关于mybatis中一级缓存和二级缓存的简单介绍 mybatis的一级缓存: MyBatis会在表示会话的SqlSession对象中建立一个简单的缓存,将每次查询到的结果结果缓存起来,当下次查询的时候 ...
- 利用Python进行数据分析(7) pandas基础: Series和DataFrame的简单介绍
一.pandas 是什么 pandas 是基于 NumPy 的一个 Python 数据分析包,主要目的是为了数据分析.它提供了大量高级的数据结构和对数据处理的方法. pandas 有两个主要的数据结构 ...
- 利用Python进行数据分析(4) NumPy基础: ndarray简单介绍
一.NumPy 是什么 NumPy 是 Python 科学计算的基础包,它专为进行严格的数字处理而产生.在之前的随笔里已有更加详细的介绍,这里不再赘述. 利用 Python 进行数据分析(一)简单介绍 ...
- yii2的权限管理系统RBAC简单介绍
这里有几个概念 权限: 指用户是否可以执行哪些操作,如:编辑.发布.查看回帖 角色 比如:VIP用户组, 高级会员组,中级会员组,初级会员组 VIP用户组:发帖.回帖.删帖.浏览权限 高级会员组:发帖 ...
随机推荐
- Winsock 编程流程
近期看了<Window程序设计>感觉在网络方面讲的不错,讲的非常通俗易懂.与大家一同交流 转载请注明出处:http://blog.csdn.net/u010484477谢谢^_^ 使用 W ...
- VB6.0数据库开发五个实例——罗列的总结
实例一: 系统登录对话框 设计分析:数据库管理系统登录对话框两种基本方法:数据库中建立数据表用于保存系统用户登录信息:支持安全验证的数据库管理系统,可将系统用户定义为数据库用户. 技术要领:1.Ent ...
- 【网络协议】TCP交互数据流和数据流成块
前言 建立在TCP协议上的应用层协议有非常多,如FTP.HTTP.Telnet等,这些协议依据数据传输的多少能够分为两类:交互数据类型和成块数据类型. 交互数据类型,如:Telnet,这类协议一般仅仅 ...
- hadoop学习;大数据集在HDFS中存为单个文件;安装linux下eclipse出错解决;查看.class文件插件
sudo apt-get install eclipse 安装后打开eclipse,提示出错 An error has occurred. See the log file /home/pengeor ...
- Linux下hp打印机驱动hplip分析
Hplip分析 版本号是2.14,源代码位置:http://hplipopensource.com. 图的来源:http://hplipopensource.com/node/128. 实践中使用的打 ...
- java基金会成立Set
1.设置 当向集合Set中添加对象时.首先集合计算要添加对象的hashcode,依据该值得到一个位置用来存放当前的对象,当在该位置没有一个对象存在的时候,集合set觉得该对象在集合中不存在,直接添加进 ...
- String,StringBuffer以及StringBuilder的差别
1.定义: String:String 类代表字符串. Java 程序中的全部字符串字面值(如"abc" )都作为此类的实例实现. 字符串是常量:它们的值在创建之后不能更改. 字符 ...
- Matlab hermite
保形分段三次hermite插值 % 这是MATLAB里面的pchip.m文件.这里把它的凝视改写成汉语,主要是想弄清楚它是怎么计算在节点处的导数的. function v = pchip(x,y,xx ...
- python学习笔记之二:使用字符串
这里会介绍如何使用字符串格式化其他的值,并了解一下利用字符串的分割,连接,搜索等方法能做些什么. 1.基本字符串操作 所有标准的序列操作(索引,分片,乘法,判断成员资格,求长度,取最大值和最小值)对字 ...
- Quasi-Newton Method--LBFGS
Quasi-Newton Method Quasi-Newton Method每一步计算过程中仅涉及到函数值和函数梯度值计算,这样有效避免了Newton Method中涉及到的Hessian矩阵计算问 ...