Hello World
Spiga

关于DLR及.NET版本的问题

2010-07-26 21:12 by 老赵, 4653 visits

动态语言运行时(Dynamic Language Runtime,DLR)是一套基于.NET的类库,它的作用是简化在CLR上开发动态语言的工作,例如DLR中提供了表达式树的创建,代码生成、优化及调试等实现动态语言的常见功能,而语言的编写者则着重关注解析器等方面的工作。不过最近接触了观察了DLR代码之后,却发现它和各版本.NET中BCL的协作还真是件不太容易理清的事情。

这还要从.NET 2.0说起,因为DLR的支持范围是.NET 2.0 SP1及.NET 4.0。.NET 2.0的类库较少,因此DLR要做的事情最多,例如它定义了一套完整的表达式树。不过到了.NET 3.5时,在新增的System.Core.dll中却也同样出现了一套表达式树的类库(例如BinaryExpression等等),而这套类库也完整包含在DLR中,它们的区别在于一个在System.Linq.Expressions命名空间下,而另一个在Microsoft.Scripting.Ast命名空间下。那么,如果您基于.NET 3.5编写代码的时候,您是利用哪一套代码?

事实上,您只能使用定义在DLR中的那套类库,因为一旦使用了.NET 3.5 BCL中的类库之后,它就无法与DLR中的其他组件进行交互了——除非您修改DLR的代码,让它与BCL中包含的表达式树进行合作。然而这么做还不一定可行,因为我们无法保证这些类库交互中是否会牵涉到内部状态。因此,在基于.NET 3.5开发DLR应用程序的时候,我们可以完全忽视BCL中表达式树的存在。

下图是DLR源代码中Codeplex-DLR.sln文件打开后的结果,其中Microsoft.Scripting.Core项目中的Ast文件夹便包含了一套“貌似”完整表达式树(抽象语法树):

不过到了.NET 4.0之后,状况又有所改变。您打开DLR源码中的Codeplex-DLR-Dev10.sln文件,便会发现Microsoft.Scripting.Core项目消失了,取而代之的是System.Core项目:

System.Core不是BCL中的类库吗?怎么会出现在DLR中?没错,这里的System.Core项目纯粹是来打酱油的,没有其他任何项目对它产生依赖。事实上,这个System.Core项目,也就是之前的Microsoft.Scripting.Core项目里的内容,已经完全融入在.NET 4的BCL里面了,它们分布在System.Core.dll的以下几个命名空间中:

  • Ast目录:System.Linq.Expressions命名空间
  • Actions目录:System.Dynamic命名空间
  • Compiler目录:System.Linq.Expressions.Compiler命名空间
  • Utils目录:System.Dynamic.Utils、System.Runtime.CompilerServices甚至System命名空间

如果您进一步阅读其中的内容,会发现代码在需要的情况下则使用了“条件编译符号”来切换其所在的命名空间,例如:

#if CLR2
namespace Microsoft.Scripting.Ast {
#else
namespace System.Linq.Expressions {
#endif

    /// <summary>
    /// Represents an expression that has a binary operator.
    /// </summary>
    public class BinaryExpression : Expression {
        ...

这样,在面向CLR 2(即.NET 2和.NET 3.5)和CLR 4的不同编译条件下,整套表达式树类库所在的命名空间是不同的。此外,如一些System.Dynamic命名空间下的类库,它们会使用条件编译符号依赖不同的表达式树类库,这也是显而易见的,例如:

#if CLR2
using Microsoft.Scripting.Ast;
using Microsoft.Scripting.Ast.Compiler;
using Microsoft.Scripting.Utils;
#else
using System.Linq.Expressions;
using System.Linq.Expressions.Compiler;
#endif

由此可见,.NET 4之前“声称”自己包含了DLR,事实上它只是包含了DLR的子集,也就是原本在Microsoft.Scripting.Core项目中的内容。那么假设我们要基于.NET 4和DLR开发一门新的语言,又该依赖哪些DLR组件呢?IronJS给了我们一个参考,您可以下载它的tag为0.1代码(目前的主代码无法编译通过),打开后便会发现它只是引用了Microsoft.Dynamic.dll和Microsoft.Scripting.dll两个程序集,其他的部分则已经包含在System.Core.dll中了:

如果我们要将其移植到.NET 3.5上,则需要引用一个额外的Microsoft.Scripting.Core.dll。我将IronJS移植到了.NET 3.5上并执行成功,项目引用情况如下:

基于我们之前的分析,其实您会发现,理想情况下将一个项目从.NET 4.0移植到.NET 3.5上并不需要修改太多代码,只要将所有对System.Linq.Expressions下类型的依赖修改至Microsoft.Scripting.Ast即可。当然在移植IronJS的过程中我还遇到了一些其他类库和语言方面的问题,例如一些使用了协变的代码,还有Enum类型中新增的HasFlag方法——幸好它没有使用C# 4.0中的dynamic,这些简单的问题只要兵来将挡,水来土掩就行了。

那么,Microsoft.Dynamic项目中究竟包含了什么呢?还是看看它的项目树吧:

您可能已经意识到了,这才是“真正”完整的DLR,包含了“真正”完整的表达式树类库及其他支持。我们有理由相信,所谓的Microsoft.Scripting.Core项目,其实只是为了.NET 4而特地分离出去的。从这点上看,DLR为了和.NET进行配合,真可谓是“用心良苦”。不过,我认为它们的做法及思路十分清晰,许多事情该怎么做,现在看来应该都是一目了然的。

Creative Commons License

本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名赵劼(包含链接),具体操作方式可参考此处。如您有任何疑问或者授权方面的协商,请给我留言

Add your comment

12 条回复

  1. Greg_lee
    60.216.223.*
    链接

    Greg_lee 2010-07-26 22:17:30

    有点看不明白,不是老赵写的不好,是本人水平太菜...

  2. 老赵
    admin
    链接

    老赵 2010-07-26 23:43:40

    @Gerg_lee

    其实我也觉得写的不给力……这些内容还是要自己看着最清楚……

  3. 链接

    zhiyuanfirst 2010-07-27 10:41:33

    虽然看不太懂,不过也支持!

  4. Rocker
    121.8.211.*
    链接

    Rocker 2010-07-28 11:59:31

    看不懂,搞得太神秘了,不适合菜鸟看。

  5. Rocker
    121.8.211.*
    链接

    Rocker 2010-07-28 12:40:38

    我想知道,为什么.NET 类库中,比如System.IO.File是静态类呢?请老赵解答,非常感谢!

    http://www.cnblogs.com/yangtongnet/archive/2010/07/28/1786751.html

  6. Bill Lo
    59.33.52.*
    链接

    Bill Lo 2010-07-28 22:38:43

    老赵的blog现在更新的好慢了啊

  7. 老赵
    admin
    链接

    老赵 2010-07-28 23:14:49

    @Rocker

    我觉得有个工具类挺好啊,真需要实例也有FileInfo嘛。

  8. HelloKitty
    222.92.145.*
    链接

    HelloKitty 2010-07-29 10:02:45

    老赵,我爱死你 了

  9. Rocker
    121.8.211.*
    链接

    Rocker 2010-07-29 12:58:40

    静态类与非静态类的本质区别是什么?不要告诉我,非静态类不需要实例化,而静态类需要实例化。小弟编程也有3-4年了,有时候总喜欢把一些公用方法写为静态方法,把共用类写为静态类,不知道这样正确与否,能否写一篇博客呢?打扰您了!

  10. 老赵
    admin
    链接

    老赵 2010-07-30 00:37:05

    @Rocker

    设计问题哪有简单的正确与否之说,我只能说我没看出File类的问题来,你的问题肯定也要具体问题具体分析了。

  11. gqqnb
    123.137.112.*
    链接

    gqqnb 2010-07-30 15:31:32

    老赵已经在用vs2010啦。。。羡慕中

  12. hyson
    221.5.67.*
    链接

    hyson 2010-10-17 11:47:05

    老赵,你是不是在.net 3.5上成功编译了ironjs了啊?在vs2008上,怎样处理可选参数的问题啊?是否可以分享下你编译成功的ironjs.dll啊?

发表回复

登录 / 登录并记住我 ,登陆后便可删除或修改已发表的评论 (请注意保留评论内容)

昵称:(必填)

邮箱:(必填,仅用于Gavatar

主页:(可选)

评论内容(大于5个字符):

  1. Your Name yyyy-MM-dd HH:mm:ss

使用Live Messenger联系我