可以随时给它增加新成员: 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 接口,可看成是一个字典对象,所 有动态添加的成员都是这个字典对象中的元素,这意味我们不仅可以添加新成 员,还可以随时移除不再需要的成员: //移除 Increment 方法 (dynamicObj as IDictionary).Remove("Increment");
方法移除之后,再尝试访问此方法将引发 RuntimeBinderException 异常。 (2) (2)使用 dynamic 关键字简化与 COM 组件交互的代码 要在.NET 这个“托管世界”里调用“非托管世界”中的 COM 组件,我们必 须通过 “互操作程序集(Interop Assembly)”作为桥梁,“互操作程序集”定 义了 CLR 类型与 COM 类型之间的对应关系。 只要给.NET 项目添加对“互操作程序集”的引用,就可以在.NET 应用
程序 中创建这一程序集所包容的各种类型的实例(即 COM 包装器对象), 对这些对象的 方法调用(或对其属性的存取)将会被转发给 COM 组件。 以调用 Word 为例,在 C# 4.0 之前您可能经常需要编写这样的代码: Object wordapp = new Word.Application(); //创建 Word 对象
Object fileName = “MyDoc.docx” ;/
/指定 Word
文档 Object argu = System.Reflection.Missing.Value; Word.Document doc = wordapp.Documents.Open(ref fileName, ref argu,
ref argu, ref argu, ref argu, ref argu, ref argu, ref argu,
ref argu, ref argu, ref argu, ref argu, ref argu, ref argu, ref argu, ref argu);
上述对 Open()方法的调用语句只能用“恐怖”一词来形容,其原因是 Word 组件中的 Open()方法定义了太多的参数。 C#4 使用 dynamic 关键字,配合从 Visual Basic 中学来的“命名参数与可 选参数”这两个新语法特性,可以写出更简洁的代码: dynamic
wordapp = new Word.Application(); dynamic doc = wordapp.Documents.Open(FileName: “MyDoc.docx”);
上述代码中省去了用不着的参数,并且可以去掉参数前的 ref 关键字。 当上述代码运行时,DLR 会使用反射技术将 dynamic 表达式“绑定(bind)” 到 COM 互操作程序集中所包容的 Word.Application 代理对象。 (3)C# 4 动态编程技术内幕 C#4 中所定义的 dynamic 变量可以引用以下类型的对象: l 传统的“静态”的 CLR 对象。 l COM 包装器对象。前面已经介绍了这方面的内容。 l 实现了 IDynamicMetaObjectProvider 接口的 “动态对象” ExpandoObject , 就是这种类型对象的实例。 l 基于 DLR 实现的动态语言(比如 IronRuby 和 IronPython)所创建的对象。 从 C#程序员角度来看,所有这四种对象都是一样的,都可用一个 dynamic 变量引用之,而 DLR 在程序运行时动态地将方法调用和字段存取请求“绑定”到 真正的对象上。 dynamic 的功能是由 DLR 所支撑的,是 C#编译器与 DLR 分工合作的成果。 请看以下示例代码:
dynamic d = 100; d++;
C#编译器在处理上述代码时,它并不去检查变量 d 是否可以支持自增操作, 而是为其创建了一个 CallSite 对象(<>p__Site1): private static class
o__SiteContainer0 { public static CallSite> <>p__S ite1; }
中文 MSDN 将 CallSite 译为“动态(调用)站点”,它是 DLR 中的核心组件之 一。 动态站点对象通过 CallSite.Create()方法创建, C#编译器会为其指定一 个派生自 CallSiteBinder 的对象(称为“动态站点绑定对象”)作为其参数。 动态站点绑定对象是与具体语言相关的,比如 IronPython 和 C#都有各自的 动态站点绑定对象。 动态站点绑定对象的主要工作是将代码中的动态表达式(本例中为 d++)转 换为一棵