ExpandoObject有什么好处?

将被添加到.NET 4的ExpandoObject类允许您在运行时随意地将属性设置到对象上。

使用Dictionary<string,object>或者甚至是一个Hashtable有没有什么好处呢? 据我所知,这只是一个哈希表,你可以用更简洁的语法来访问。

例如,为什么是这样的:

 dynamic obj = new ExpandoObject(); obj.MyInt = 3; obj.MyString = "Foo"; Console.WriteLine(obj.MyString); 

与以下方面相比,真的更好,或者说与之大不相

 var obj = new Dictionary<string, object>(); obj["MyInt"] = 3; obj["MyString"] = "Foo"; Console.WriteLine(obj["MyString"]); 

使用ExpandoObject而不是仅仅使用任何字典types会带来什么真正的好处,除了不明显的是你使用的types将在运行时被确定。

由于我写了你所指的MSDN文章,我想我必须回答这个问题。

首先,我预料到了这个问题,这就是为什么我写了一篇博客文章,展示了ExpandoObject: Dynamic in C#4.0中的一个或多或less的真实用例:介绍ExpandoObject 。

简而言之,ExpandoObject可以帮助您创build复杂的分层对象。 例如,假设在字典中有一个字典:

 Dictionary<String, object> dict = new Dictionary<string, object>(); Dictionary<String, object> address = new Dictionary<string,object>(); dict["Address"] = address; address["State"] = "WA"; Console.WriteLine(((Dictionary<string,object>)dict["Address"])["State"]); 

层次越深,丑陋就是代码。 借助ExpandoObject,它保持优雅和可读性。

 dynamic expando = new ExpandoObject(); expando.Address = new ExpandoObject(); expando.Address.State = "WA"; Console.WriteLine(expando.Address.State); 

其次,正如已经指出的那样,ExpandoObject实现了INotifyPropertyChanged接口,它使您能够比字典更好地控制属性。

最后,您可以像这样将事件添加到ExpandoObject:

 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); } } 

一个好处是绑定的情况。 数据网格和属性网格将通过TypeDescriptor系统获取dynamic属性。 另外,WPF数据绑定将理解dynamic属性,因此WPF控件可以比字典更容易地绑定到ExpandoObject。

与dynamic语言的互操作性在某些情况下也可能是一个考虑因素,而dynamic语言的期望DLR属性而不是字典条目。

对我来说真正的好处是XAML完全不费吹灰之力的数据绑定:

 public dynamic SomeData { get; set; } 

 SomeData.WhatEver = "Yo Man!"; 

  <TextBlock Text="{Binding SomeData.WhatEver}" /> 

DLR上build立的其他语言DLR是我能想到的第一个理由。 你不能将它们传递给Dictionary<string, object>因为它不是一个IDynamicMetaObjectProvider 。 另一个额外的好处是它实现了INotifyPropertyChanged ,这意味着在WPF的数据绑定世界中,除了Dictionary<K,V>可以为您提供的好处之外,它还带来了好处。

这完全是关于程序员的方便。 我可以想象用这个对象编写快速和肮脏的程序。

我认为它会有一个语法上的好处,因为你将不再使用字典“伪装”dynamic添加的属性。

那么,我会考虑dynamic语言。

这是关于使用ExpandoObject为传入结构化数据(即XML,Json)创builddynamic临时types的很好的MSDN文章的例子。

我们也可以将委托分配给ExpandoObject的dynamic属性:

 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); 

因此,它允许我们在运行时注入一些逻辑到dynamic对象中。 因此,与lambdaexpression式,闭包,dynamic关键字和DynamicObject类一起 ,我们可以将函数式编程的一些元素引入我们的C#代码中,我们从dynamic语言就像JavaScript或PHP一样了解这些代码。

有些情况下,这是方便的。 例如,我将使用它作为Modularizedshell。 每个模块定义了它自己的configuration对话框数据绑定到它的设置。 我为它提供一个ExpandoObject,因为它是Datacontext,并将这些值保存在我的configuration存储中。 这种方式configuration对话框编写器只需绑定到一个值,它会自动创build和保存。 (并提供给模块使用这些设置当然)

它比“字典”简单易用。 但每个人都应该知道,内部它只是一个字典。

这就像LINQ只是语法糖,但它有时使事情更容易。

所以要直接回答你的问题:写起来更容易,更容易阅读。 但从技术上讲,它基本上是一个Dictionary<string,object> (你甚至可以把它转换成一个来列出值)。

 var obj = new Dictionary<string, object>; ... Console.WriteLine(obj["MyString"]); 

我认为这只是因为一切都有一个ToString(),否则你将不得不知道它的types,并将“对象”转换为该types。


其中一些比其他更有用,我试图彻底。

  1. 使用更直接的点符号来访问一个集合,在这种情况下,实际上是一个“字典”可能更自然。

  2. 这似乎可以用作一个非常好的元组。 你仍然可以打电话给你的成员“Item1”,“Item2”等等,但是现在你不需要,它也是可变的,不像Tuple。 这确实有缺乏智能支持的巨大缺陷。

  3. 您可能会觉得“成员名称是string”,就像字典的感觉一样,您可能会觉得它太像“正在执行的string”,并且可能导致命名约定被编入,并且处理使用词素和音节当代码尝试了解如何使用成员:-P

  4. 你可以给ExpandoObject本身赋值,还是只是它的成员? 与dynamic/dynamic[]进行比较和对比,使用最适合您的需求。

  5. 我不认为dynamic/dynamic[]工作在一个foreach循环,你必须使用var,但可能你可以使用ExpandoObject。

  6. 你不能在类中使用dynamic的数据成员,也许是因为它至less有点像关键字,希望你可以用ExpandoObject。

  7. 我期望它是“一个ExpandoObject”,可能会非常有用地标记非常通用的东西,代码区分的基础上有很多dynamic的东西被使用的types。


如果可以一次钻取多个层次,那就好了。

 var e = new ExpandoObject(); e.position.x = 5; etc... 

这不是最好的例子,想象在你自己的项目中适当的优雅使用。

这是一个耻辱,你不能有代码build立其中的一些,并推动结果intellisense。 我不知道这将如何工作。

如果能和成员一样有价值,那就好。

 var fifteen = new ExpandoObject(); fifteen = 15; fifteen.tens = 1; fifteen.units = 5; fifteen.ToString() = "fifteen"; etc...