.NET 4和VS2010新技术亮点选析

文 金旭亮

  原文链接:http://www.programmer.com.cn/3774/ 


微软公司宣布, 2010年4月12日,在全球同步发布.NET 4和Visual Studio 2010。

作为微软平台最重要的产品,.NET 4和Visual Studio 2010所带来的诸多新技术成为了众人关注的焦点,本文将选取其中几个重要的技术创新点,介绍其来龙去脉,点出其设计思路,剖析其技术关键,展示其应用前景,从而帮助读者在这一轮新技术浪潮中占据先机。


保证代码质量的强有力工具:Code Contract

防卫型编程风格已为广大程序员所熟悉,最典型的做法是在函数开头书写代码检测传入参数的有效性,发现无效参数时抛出一个异常。

“防卫式编码”简单而有效,因而在实际开发中得到了广泛应用。

但是,任何事物都不是完美无缺的,“防卫式编码”也一样,因为它要求在执行真正的功能代码前进行一些检测工作,因此必然会引入一些额外的开销,如果某些检测工作还比较复杂,对程序运行效率会有负面影响。

为了避免这种情况的出现,人们就想出一个“两全其美”的方法——使用“条件编译”。通过定义条件编译符号控制编译器是否编译特定的代码。

从.NET 4开始,软件工程师们多了一个选择,这就是“代码协定(Code Contract)”。

代码协定(Code Contract)的核心类是“Contract”,以下是一个示例:

static double Divide(double divisor, double dividend)

{

Contract.Requires(divisor >= 0 && dividend > 0,

“除数与被除数必须大于0,并且除数不能为0″);

return divisor / dividend;

}

如果只是重复已有的功能,那么“代码协定”就没有太多存在的意义,事实上,它的最强大之处在于提供了一系列的静态方法实现 “协定式编程”。

“协定式编程”要求软件工程师在设计和编写代码时必须考虑:

  • 方法调用入口所必须满足的条件,称为“前条件(precondition)”
  • 方法调用出口所必须满足的条件,称为“后条件(postcondition)”。
  • 方法调用前后,必须始终满足的条件是什么,称为“不变量(invariant)”。

由此可见,“协定式编程”能清晰地传递“原始”开发者的设计意图,使得代码调用者在编写新代码时有所参照,无须另外查找文档。

.NET 4将代码协定相关的类型移入到.NET核心程序集Mscorlib.dll中,成为CLR功能集的组成部分,对所有.NET编程语言“一视同仁”地给予了代码协定的支持。


使用MEF开发拥抱变化的软件系统

.NET 4引入了一个“Managed Extensibility Framework(MEF)”,开发支持插件的软件系统变得前所未有的简单。


MEF的基本原理

将一个MEF应用程序可看成是多个“可组合部件(Composable Part)”的集合,通过简单地给部件附加“[Import]”和“[Export]”标记,可以清晰地表明部件之间的“服务消费”与“服务提供”关系(图 1)。

图1  可组合部件示意图

图1 可组合部件示意图

“导入(Import)”描述了一个部件需要什么。“导出(Export)”描述了一个部件能提供什么。

从面向对象的角度来看,MEF其实就是将类之间的组合关系转换为“导入(需要外界提供的服务)”和“导出(向外界提供服务)”罢了。

导入与导出之间必须相互匹配,匹配的标准由“协定(contract)”进行描述。协定由“协定名(ContractName)”和“元数据(Metadata)”组成。

协定名通常就是导出所关联的字段或属性类型的完整名称。

元数据其实是一个“名称/值”的集合,在实际开发中,程序员可以给部件附加特定的元数据,然后在部件宿主程序中查询这些元数据,完成特定的功能。

装配部件为一个完备的软件系统的过程称为“组合(Compose)”,由部件“组合容器(Composition Container)”完成。每个需要装配部件的.NET部件宿主程序都至少创建一个部件组合容器对象。

部件组合容器为了完成“为部件宿主程序创建合适的部件对象”的工作,必须知道以下信息:

  • 有哪些部件可用。
  • 这些部件之间的依赖关系。

MEF使用 “部件编目(Catalog)”来封装上述信息。

部件组合容器通过查询Catalog,就能获得它所需要的信息,然后,在底层使用反射动态地完成组件识别、装配工作。


MEF的具体应用

在实际项目中,我们可以将系统中需要动态扩展或升级的部分封装为部件,将其编译为独立的程序集(一个程序集中可以包容多个部件),通过MEF完成部件的实时装配。由此可见,MEF可用于实现系统的可扩充点,多用于应用系统的中间层。

需要特别指出的是,Silverlight 4支持MEF。

可以给一个Silverligtht页面附加[Import]标记,指明它可以装配部件,类似地,通过给Silverlight“用户控件(User Control)”附加[Export]标记,每个用户控件就可以成为一个可组合的部件,我们可以将这些用户控件编译为独立的Silverlight程序集,放置在网站的特定文件夹下。

当用户访问Silverlight应用程序时,开始可以只显示一个“初始的简单的”页面,当用户需要时,再动态从Web网站上下载新的Silverlight程序集(这利用了Silverlight所支持的“按需下载(download on demand)”功能),然后,Silverlight客户端应用程序再使用MEF将程序集中所包容的页面组件“组装”为一个新的功能增强了的Silverlight页面。

应用这种技术,可以减少Silverlight客户端与Web服务器间的数据流量,提升Silverlight应用程序的响应性能,同时,也使得Silverlight应用程序的动态扩展变得简单。


迈入多核时代

多核化是CPU确定不移的发展方向,双核CPU早已普及,装备有四核CPU的个人电脑正在热卖,所有一切都告诉我们,硬件技术的发展推动着软件开发进入了多核时代。

.NET 4为程序员提供了强大的工具以迎接这一技术挑战。


线程取消模型

.NET 4在多线程开发中新推出了一个引人注目的线程“统一取消模型(Unified Model for Cancellation)”。

这个模型的核心是两个类:CancellationToken和CancellationTokenSource。

CancellationToken称为“取消令牌”,它用于代表一个外界的“取消操作”请求。

.NET4所提供的线程统一取消模型可以简述如下。

  • 创建CancellationTokenSource对象,它包容了一个取消令牌对象,外界可以通过其Token属性获取“取消令牌”。
  • 设计可以被“中断”的线程函数,在此函数中检测取消令牌的IsCancellationRequested属性,从而知道是否应该中止执行。
  • 需要取消线程执行时,调用CancellationTok-enSource类的Cancel()方法即可。

.NET 4所引入的线程统一取消模式,规范了多线程程序中“提前结束”线程的方式,在.NET 4新增加的类和组件中得到了较为广泛的应用。


并行任务库

“任务并行库(Task Parallel Library :TPL)”是.NET 4为帮助软件工程师开发并行程序而提供的一组类,位于System.Threading和System.Threading.Tasks这两个命名空间中,驻留在3个.NET核心程序集Mscorlib.dll、System.dll和 System.Core.dll里。使用这些类,可以让软件工程师在开发并行程序时,更关注于问题本身,而不是诸如线程的创建、取消和同步等烦琐的技术细节。

使用TPL开发并行程序,考虑的着眼点是“任务(task)”而非“线程”。

一个任务是一个Task类的实例,它代表某个需要计算机执行的数据处理工作,其特殊之处在于:

在TPL中,任务通常代表一个可以被计算机并行执行的工作。

任务可以由任何一个线程执行,特定的任务与特定的线程之间没有绑定关系。在.NET 4中,TPL使用.NET线程池中的线程来执行任务。

负责将任务“分派”到线程的工作由“任务调度器(Task Scheduler)”负责。任务调度器集成于线程池中。

1 Parallel类

在TPL中,最容易使用的类是Parallel,此类提供了三个方法“群”用于实现三种常用的并行程序执行结构。

(1)使用Parrallel.Invoke()方法可以让多条语句并行执行:

Parallel.Invoke(

() => StatementA(),

() => StatementB(),

() => StatementC() );

(2)使用Parrallel.For()方法启动并行循环

Parallel.For(0, 100, (i) => DoWork(i));

(3)如果你有一大堆“单个”的数据,并且每个数据都需要进行同样的处理,并且这些处理可以并行,那么使用Parallel.ForEach()方法可以实现这些处理工作的并行执行。

Parallel.ForEach(sourceCollection, item => Process(item));

2 Task类

TPL提供了多种手段实现多任务间的同步。例如,以下代码在task1完成之后自动运行task2:

Task task1=new Task(()=>

{

DoStep1();

});

Task task2 = task1.ContinueWith((PrevTask) =>

{

DoStep2();

});

task1.Start();

使用Task开发,比直接使用Thread要方便许多。

3 并行LINQ

PLINQ主要用于并行执行数据查询,而它本身又是.NET 4所引入的并行扩展的有机组成部分,因此,它与LINQ和TPL都有着密切的联系。

在目前的版本中,PLINQ只实现了LINQ to Object的并行执行。

将LINQ查询转换为PLINQ非常简单,在许多情况下只需简单地添加一个AsParallel子句就行了,例如,以下代码将把整数集合中的偶数挑出来:

//创建一个100个元素的整数集合,保存从1到100的整数.

var source = Enumerable.Range(1, 100);

var evenNums = from num in source.AsParallel()

where num % 2==0

select num;

与LINQ类似,PLINQ也具有“延迟执行”的特性,只有对查询集合调用foreach迭代、或者调用ToList()之类方法时,PLINQ查询才会真正执行。

另外,PLINQ在底层使用TPL所提供的基础架构完成所有工作,因此,PLINQ是比“Task”抽象层次更高的编程手段。

总之,在设计并行程序时,推荐按照以下顺序来设计技术解决方案:

基于PLINQ的声明式编程方式→使用Task的直接基于TPL的“任务并行”编程方式→使用线程的基于CLR的“多线程”编程方式。


使用Silverlight 4开发多层商业应用

Visual Studio 2010的正式版本中集成了Silverlight 4,与以前的版本相比,Silverlight 4带来了众多的新变化,最大的亮点是Silverlight 4已成为了一个强大的商业应用开发平台。

图2所示为一个典型的Silverlight多层应用程序架构。

图2  Silverlight多层应用程序架构

图2 Silverlight多层应用程序架构

如图2所示,在Web服务端我们使用ASP.NET应用程序作为WCF RIA Service的宿主,使用ADO.NET实体框架封装数据。

WCF RIA Service在服务端将业务逻辑功能封装为“领域服务(Domain Service)”,Visual Studio 2010在编译项目时,会同时生成此领域服务的客户端代理类(派生自DomainContext),Silverlight 4提供了一个DomainDataSource组件作为数据绑定源,诸如TextBlock和DataGrid之类客户端数据绑定控件可以直接绑定到DomainDataSource组件。

可以这么说,Silverlight直到4.0版本才算是成为了一个真正的商业应用开发平台,我想这将大大地促进其推广和应用。


.NET编程语言新成员:F#

函数式编程语言拥有很长的历史,但大多局限于学术界使用,直到Visual Studio 2010中新添加了F#,才使函数式编程开始走向真正的商业应用。

Visual Studio 2010为F#提供了方便和强大的编辑手段,只需在代码编辑器中选中要执行的F#语句,按Alt+Enter组合键,就可以直接在Visual Studio 2010集成的F# Interactive窗口显示结果。

与其他的函数式编程语言Lisp、OCaml等不一样,F#是一个“混血儿”,它同时支持函数式和面向对象两种编程风范,并且可以直接调用.NET基类库中的各种组件,它所开发出来的组件也可以被其他.NET编程语言所调用。

由于F#中的数据结构都是不可改(immutable)的,因此如果使用它来开发多线程程序会非常简单,因为它无须耗用计算资源来进行解决多线程开发中的“竞台条件(race condition)”共享资源的问题。另外,函数式编程的风格,使得F#在实现某些计算机算法时显得简洁而高效,因此,预计F#会在计算密集型的应用系统中有较好的表现。


新时代的曙光——云计算

微软首次将对云计算的支持直接融入到Visual Studio 2010中,微软的云计算应用依托于Azure这个云计算平台。

如果希望在云计算应用中访问传统的关系型数据,微软提供了一个SQL Azure服务,云计算应用访问此服务,非常类似于传统.NET应用程序为了方便用户开发云计算应用,微软在Visual Studio 2010中提供了一个本地的Azure开发环境(称为“Windows Azure Simulation Environment”),它使用本地的SQL Server Express作为数据存储。毫无疑问,云计算将是下一个十年中软件技术竞争的主战场,从微软在Visual Studio 2010中首次集成云计算应用开发功能这一现象上,我们似乎已经嗅到了一场技术大战的硝烟:一个新时代正在向我们走来!


作者简介:

金旭亮金旭亮,任教于北京理工大学计算机学院,15年开发经验,8年从教生涯,已著三本.NET技术书籍和大学教材。中国高校计算机教育改革的实践者,致力于软件技术的应用与推广,为计算机专业学生和程序员个人提供技术学习指导,为企业提供员工.NET技术系统培训服务。

posted @ 2010-08-20 13:39  博文视点  阅读(857)  评论(1编辑  收藏  举报