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。
其中一些比其他更有用,我试图彻底。
-
使用更直接的点符号来访问一个集合,在这种情况下,实际上是一个“字典”可能更自然。
-
这似乎可以用作一个非常好的元组。 你仍然可以打电话给你的成员“Item1”,“Item2”等等,但是现在你不需要,它也是可变的,不像Tuple。 这确实有缺乏智能支持的巨大缺陷。
-
您可能会觉得“成员名称是string”,就像字典的感觉一样,您可能会觉得它太像“正在执行的string”,并且可能导致命名约定被编入,并且处理使用词素和音节当代码尝试了解如何使用成员:-P
-
你可以给ExpandoObject本身赋值,还是只是它的成员? 与dynamic/dynamic[]进行比较和对比,使用最适合您的需求。
-
我不认为dynamic/dynamic[]工作在一个foreach循环,你必须使用var,但可能你可以使用ExpandoObject。
-
你不能在类中使用dynamic的数据成员,也许是因为它至less有点像关键字,希望你可以用ExpandoObject。
-
我期望它是“一个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...