What are the true benefits of ExpandoObject?
添加到.NET 4中的ExpandooObject类允许您在运行时任意设置对象的属性。
与使用
例如,为什么:
1 2 3 4 | dynamic obj = new ExpandoObject(); obj.MyInt = 3; obj.MyString ="Foo"; Console.WriteLine(obj.MyString); |
比以下情况更好,或大不相同:
1 2 3 4 5 | var obj = new Dictionary<string, object>(); obj["MyInt"] = 3; obj["MyString"] ="Foo"; Console.WriteLine(obj["MyString"]); |
使用expandoobject而不是使用任意的字典类型,除了不明显您使用的是将在运行时确定的类型之外,还可以获得哪些真正的优势。
既然我写了你所指的msdn文章,我想我必须回答这个问题。
首先,我预料到了这个问题,这就是为什么我写了一篇博客文章,展示了expandoobject:dynamic在C 4.0中的一个或多或少真实的用例:介绍expandoobject。
很快,Expandoobject可以帮助您创建复杂的层次对象。例如,假设您在字典中有一个字典:
1 2 3 4 5 |
层次结构越深,代码越难看。通过Expandoobject,它保持优雅和可读性。
1 2 3 4 |
第二,正如已经指出的,Expandoobject实现了InotifyPropertyChanged接口,它为您提供了比字典更多的对属性的控制。
最后,可以向expandoobject添加事件,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | class Program { static void Main(string[] args) { dynamic d = new ExpandoObject(); // Initialize the event to null (meaning no handlers) d.MyEvent = null; // Add some handlers d.MyEvent += new EventHandler(OnMyEvent); d.MyEvent += new EventHandler(OnMyEvent2); // Fire the event EventHandler e = d.MyEvent; if (e != null) { e(d, new EventArgs()); } // We could also fire it with... // d.MyEvent(d, new EventArgs()); // ...if we knew for sure that the event is non-null. } static void OnMyEvent(object sender, EventArgs e) { Console.WriteLine("OnMyEvent fired by: {0}", sender); } static void OnMyEvent2(object sender, EventArgs e) { Console.WriteLine("OnMyEvent2 fired by: {0}", sender); } } |
一个优点是绑定场景。数据网格和属性网格将通过typescriptor系统获取动态属性。此外,WPF数据绑定将了解动态属性,因此WPF控件比字典更容易绑定到Expandoobject。
在某些情况下,与动态语言的互操作性也可能是一个考虑因素,因为动态语言需要DLR属性而不是字典条目。
对我来说,真正的好处是XAML完全可以轻松地进行数据绑定:
1 | public dynamic SomeData { get; set; } |
…
1 | SomeData.WhatEver ="Yo Man!"; |
…
1 | <TextBlock Text="{Binding SomeData.WhatEver}" /> |
与基于
这都是为了程序员的方便。我可以想象用这个对象编写快速而脏的程序。
我认为它将有一个句法上的好处,因为您将不再使用字典来"伪造"动态添加的属性。
我认为,它可以与动态语言互操作。
这是有关使用expandoobject为传入的结构化数据(即XML、JSON)创建动态即席类型的伟大的msdn文章中的示例。
我们还可以将委托分配给Expandoobject的动态属性:
1 2 3 4 5 6 7 8 9 10 11 | dynamic person = new ExpandoObject(); person.FirstName ="Dino"; person.LastName ="Esposito"; person.GetFullName = (Func<String>)(() => { return String.Format("{0}, {1}", person.LastName, person.FirstName); }); var name = person.GetFullName(); Console.WriteLine(name); |
因此,它允许我们在运行时向动态对象注入一些逻辑。因此,与lambda表达式、闭包、动态关键字和dynamicObject类一起,我们可以将函数编程的一些元素引入到我们的C代码中,我们从诸如javascript或php之类的动态语言中了解到这些元素。
有些情况下这很方便。例如,我将把它用于模块化的shell。每个模块定义它自己的配置对话框数据绑定到它的设置中。我为它提供了一个expandoobject作为dataContext,并将值保存在我的配置存储中。这样,配置对话框编写器只需绑定到一个值,它就会自动创建和保存。(并提供给模块使用这些设置)
它比字典更容易使用。但每个人都应该知道,在内部,它只是一本字典。
它就像LINQ只是句法上的糖分,但有时会让事情变得更容易。
所以直接回答你的问题:写起来容易,读起来容易。但从技术上讲,它本质上是一个
1 2 3 |
我认为这只会起作用,因为每件事都有一个toString(),否则你必须知道它是什么类型,并将"object"强制转换为那个类型。
其中一些比其他的更有用,我正在努力做到彻底。
使用更直接的点表示法访问集合可能更自然,在本例中,什么是有效的"字典"。
这似乎可以用作一个非常好的元组。你仍然可以称你的成员为"项目1"、"项目2"等…但是现在你不需要了,它也是可变的,不像元组。这确实存在缺乏智能感知支持的巨大缺点。
你可能会对"成员名作为字符串"感到不舒服,就像字典里的感觉一样,你可能会觉得它太像"执行字符串",它可能导致命名约定被编码,以及在代码试图理解如何使用成员时处理语素和音节的问题。
可以将值赋给Expandoobject本身或只是它的成员吗?与动态/动态[]进行比较和对比,使用最适合您需要的工具。
我认为dynamic/dynamic[]在foreach循环中不起作用,您必须使用var,但可能可以使用expandoobject。
您不能将dynamic用作类中的数据成员,可能是因为它至少有点像关键字,希望您可以使用expandoobject。
我希望它"是"一个expandoobject,可能有助于将非常普通的事物分开,代码根据使用了大量动态事物的类型进行区分。
如果你能一次钻取多个层面,那就太好了。
1 2 3 |
这不是最好的例子,想象一下在你自己的项目中优雅的使用。
很遗憾,您不能让代码构建其中的一些,并将结果推送到IntelliSense。不过,我不确定这会如何运作。
如果他们既有成员又有价值,那就好了。
1 2 3 4 5 6 | var fifteen = new ExpandoObject(); fifteen = 15; fifteen.tens = 1; fifteen.units = 5; fifteen.ToString() ="fifteen"; etc... |
在valuetuples之后,expandoobject类的用途是什么?这6行代码使用expandoobject:
1 2 3 4 5 6 |
可以用元组在一行中写入:
1 | var T = (x: 1, y: 2, z: (a: 3, b: 4)); |
除了元组语法之外,您还具有强大的类型推断和intlisense支持。