前言
为了让C#、Visual Basic等.NET编程语言能具备动态编程语言的特性,.NET 4.0引入了一个“DLR(Dynamic Language Runtime:动态语言运行时)”(图 3)。
DLR运行于CLR之上,提供了一个动态语言的运行环境,从而允许Python、Ruby等动态语言编写的程序在.NET平台上运行,同时,现有的.NET静态类型编程语言,比如C#和Visual Basic,也可以利用DLR而拥有一些动态编程语言的特性。
为什么动态代码第一次慢,后面就解决静态语言了
由于DLR自身设计了一个“规则”缓存系统(DLR设计了一个三级缓存策略),又充分利用了CLR所提供的JIT缓存(因为所有动态调用代码最终都会转换为CLR可以执行的IL指令,而CLR可以缓存这些代码),使得动态代码仅仅在第一次执行时性能较差,后续的连续调用其性能可以逼近静态代码。
(1)使用C# 4编写动态的代码
C# 4新增了一个dynamic关键字,可以用它来编写“动态”的代码。
例如,以下代码创建了一个ExpandoObject对象(注意必须定义为dynamic):
dynamic dynamicObj = new ExpandoObject();
这一对象的奇特之处在于,我们可以随时给它增加新成员:
dynamicObj.Value = 100; //添加字段
dynamicObj.Increment = new Action(() => dynamicObj.Value++); //添加方法
这些动态添加的成员与普通的类成员用法一样:
for (int i = 0; i < 10; i++)
dynamicObj.Increment();//调用方法
Console.WriteLine(“dynamicObj.Value={0}”,dynamicObj.Value);//访问字段
ExpandoObject对象实现了IDictionary<string, object>接口,可看成是一个字典对象,所有动态添加的成员都是这个字典对象中的元素,这意味我们不仅可以添加新成员,还可以随时移除不再需要的成员:
//移除Increment方法
(dynamicObj as IDictionary<string, object>).Remove(“Increment”);
方法移除之后,再尝试访问此方法将引发RuntimeBinderException异常。
表达式树和动态语言运行时(DLR)是什么关系
动态语言运行时(DLR)
动态语言运行时(Dynamic Language Runtime, DLR)是处理动态对象的一种便捷方法。比如,假设您有 XML 或 JSON 格式的数据,其中的成员事先并不知道。DLR 允许您使用自然代码来处理对象和访问成员。
对于 C#,这使您可以处理在编译时不知道其类型的库。动态类型消除了自然 API 代码中的万能字符串。这就开启了像 IronPython 一样位于 CLR 之上的动态语言。
DLR 向 CLR 添加了一组服务,以便更好地支持动态语言。 这些服务包括:
- 表达式树。 DLR 使用表达式树来表示语言语义。 为此,DLR 扩展了 LINQ 表达式树,使其包含控制流、分配和其他语言建模节点。 有关详细信息,请参阅表达式树 (C#) 或表达式树 (Visual Basic)。
- 调用点缓存。 动态调用点是代码中对动态对象执行
a + b
或a.b()
等操作的位置 。 DLR 会缓存a
和b
(通常为这些对象的类型)的特征,以及有关操作的信息。 如果之前已经执行过此类操作,则 DLR 会从缓存中检索所有的必要信息,以实现快速调度。 - 动态对象互操作性。 DLR 提供一组表示动态对象和操作的类和接口,供语言实现者和动态库的作者使用。 这些类和接口包括IDynamicMetaObjectProvider、DynamicMetaObject、DynamicObject 和 ExpandoObject。
要了解 DLR 和 CLR 是如何结合在一起的,请看下图:
DLR 支持高级多态缓存,因此可以快速执行动态操作。
总结
即我们所知道的调用点缓存来避免每次动态代码被调用时的重新编译。动态分配确保适当的语言结合(Language Binders)能够用于动态调用。
C# 动态类型或许看起来令人望而生畏,但它在强类型系统之上有很多好处。DLR 是所有动态操作发生和与 CLR 交互的地方,类型继承使同时处理这两个类型系统变得容易。在 C# 中,动态和静态编程之间并没有对立,这两种类型系统共同协作,以创造性的方式解决动态问题。
https://ittranslator.cn/dotnet/csharp/2021/01/20/working-with-the-dynamic-type-in-csharp.html
https://docs.microsoft.com/zh-cn/dotnet/framework/reflection-and-codedom/dynamic-language-runtime-overview