对象的主要工作是将代码中的动态表达式(本例中为 d++)转 换为一棵“抽象语法树(AST:Abstract Syntax Tree)”,这棵语法树被称为“DLR Tree”,是在.NET 3.5 所引入的 LINQ 表达式树的基础上扩充而来的,因此,有 时又称
其为“表达式树(Expression Tree)” DLR 在内部调用此表达式树的 Compile()方法生成 IL 指令, 得到一个可以被 CLR 所执行的委托(在本例中其类型就是 Func)。 动态调用站点对象(本例中为<>p__Site1)有一个 Target 属性,它负责引用 这一生成好的委托。 委托生成之后,动态表达式的执行就体现为委托的执行,其实参由 C#编译 器直接“写死”在 IL 代码中。 简化的代码示意如下(通过 Reflector 得到,为便于阅读,修改了变量名): object d = 100; object CS$0$0000 = d;
if (<>p__Site1 == null) <>p__Site1 = CallSite
>.Create (……); d = <>p__Site1.Target(<>p__Site1, CS$0$0000);
上述类型推断、方法绑定及 IL 代码生成的工作都是在程序运行时完成的。 (4)动态代码很慢吗? (4)动态代码很慢吗? 动态代码很慢吗 动态编程语言易学易用, 代码紧凑, 开发灵活, 但性能则一直是它的 “软肋” 。 为了提升性能,DLR 设计了一个三级缓存策略。 动态站点绑定对象会为动态调用表达式转换而成的语法树加上相应的测试 条件(称为“test”),构成一个“规则(Rule)”,这个规则可以用于判断某个语 法树是否可用于特定的动态调用表达式。 举个例子,请看以下这个动态表达式: d1 + d2
如果在程序运行时 d1 和 d2 都是 int 类型的整数,则 DLR 生成的规则为: if( d1 is int &;&; d2 is int) //测试条件 return (int)d1+(int)d2; //语法树
DLR 通过检查规则中的“测试条件”,就可以知道某个动态表达式是否可以 使用此规则所包容的语法树。 “规则”是 DLR 缓存的主要对象。 前面介绍过的动态站点对象 Target 属性所引用的委托是第一级缓存,它实 现的处理逻辑是这样的: //当前处理规则,属于第 1 级缓存 if( d1 is int &;&; d2 is int) //测试条件
return (int)d1+(int)d2; //满足测试条件,直接返回一个表达式树 //未命中,则在第 2 级、第 3 级缓存中查找,如果找到了,用找到的结果更 新第 1 级缓存 return site.Update(site,d1,d2);
如果 3 级缓存中都没有命中的规则, 则此动态站点所关联的调用站点绑定对 象会尝试创建一个新的规则。 如果创建新规则失败, 则由当前编程语言(比如 C#) 所提供的默认调用站点绑定对象决定如何处理,通常的作法是抛出一个异常。 当前版本的 DLR 第 2 级缓存了 10 条规则,第 3 级则缓存了 100 条规则。 由于 DLR 自身设计了一个“规则”缓存系统,又充分利用了 CLR 所提供的 JIT 缓存(因为所有动态调用代码最终都会转换为 CLR 可以执行的 IL 指令, CLR 而 可以缓存这些代码),使得动态代码仅仅在第一次执行时性能较差,后续的连续 调用其性能可以逼近静态代码。 3 C# 4 与动态语言的集成
由于几乎所有的编程语言都可以使用抽象语法树来表达,因此,在理论上 DLR 支持无限多种编程语言间的互操作,在当前版本中,可以实现 C#/Visual Basic 与 IronPython 和 IronRuby 的互操作,相信很快会出现其他动态编程语言 的 DLR 实现。 一个有趣的地方是当前基于 DLR 实现的动态编程语言都以“Iron”开头,比 如 IronRuby 和 IronPython。 IronPython 的设计者、 的架构设计师 Jim Hugunin DLR 曾经在微软 PDC 2008 大会上解释说主要是为了避免起一个“Python.NET”或 “Python for .NET”之类“微软味十足”的名字,才有了“IronPython”。他 强调:“Iron”系列动态语言将严格遵循动态语言自身的标准和规范,尊重这些 动态语言已有的历史和积累,不会引入一些仅限于.NET 平台的新语言特性,并 且这些语言的.NET 实现保持开源。与此同时,Jim Hugunin 指出 “Iron”系列 语言能很好地与.NET 现有类库、编程语言和工具集成,并且能“嵌入”到.NET 宿主程序中。 (1)动态对象通讯协议 (1)动态对象通讯协议 由于各种动态编程语言之间的特性相差极大, 实现各语言间的互操作是个难 题。为此 DLR 采取了一个聪明的策略,它不去尝试设计一个“通用的类型系统” (CLR 就是这么干的),而是设计了一个“通用的对象通讯协议”,规定所有需要 互操作的动态对象必须实现 IDynamicMetaObjectProvider 接口,此接口定义了
一个 GetMetaObject()方法, 接收一个语法树对象作为参数, 向外界返回一个 “动 态元数据(DynamicMetaObject)”对象: DynamicMetaObject GetMetaObject(Expression parameter);
DynamicMetaObject 对象向外界提供了两个重要属性: Restrictions 引用一 组测试条件,Expression 属性则引用一个语法树。这两个属性组合起来就是可 供动态站点对象缓存的“规则(Rule)”。 DLR 中的 “动态站点绑定对象(CallSiteBinder)” 获取了 DynamicMetaObject 对象之后,它调用此对象所提供的各个方法创建“规则”,让“动态站点对象 (CallSite)”的 Tar
上一篇:影响软件开发效率的12大杀手_Ruby代码
下一篇:银行信用风险管理论文:商业银行全面风险管理模式信息管理系统试论