ExpandoObject的真正好处是什么?

Ree*_*sey 573 .net c# .net-4.0 c#-4.0

添加到.NET 4 的ExpandoObject类允许您在运行时任意设置对象的属性.

使用a Dictionary<string, object>或者甚至是Hashtable有什么优势吗?据我所知,这只是一个哈希表,您可以使用稍微简洁的语法访问.

例如,为什么这样:

dynamic obj = new ExpandoObject();
obj.MyInt = 3;
obj.MyString = "Foo";
Console.WriteLine(obj.MyString);
Run Code Online (Sandbox Code Playgroud)

真的比以下更好,或者大不相同:

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

Console.WriteLine(obj["MyString"]);
Run Code Online (Sandbox Code Playgroud)

使用ExpandoObject而不是仅仅使用任意字典类型可以获得什么真正的优势,除了不明显你正在使用将在运行时确定的类型.

Ale*_*ina 675

自从我写了你所指的MSDN文章以来,我想我必须回答这个问题.

首先,我预料到了这个问题,这就是为什么我写了一篇博文,展示了一个或多或少真实的ExpandoObject用例:C#4.0中的动态:介绍ExpandoObject.

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

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"]);
Run Code Online (Sandbox Code Playgroud)

层次结构越深,代码越丑.使用ExpandoObject,它保持优雅和可读性.

dynamic expando = new ExpandoObject();
expando.Address = new ExpandoObject();
expando.Address.State = "WA";
Console.WriteLine(expando.Address.State);
Run Code Online (Sandbox Code Playgroud)

其次,正如已经指出的那样,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);
   }
}
Run Code Online (Sandbox Code Playgroud)

  • 有趣.感谢您提供的信息:事件.对我来说这是一个新的. (51认同)
  • 也许我错过了一些东西,但这不是事件 - 这是委托类型的简单属性. (19认同)
  • @AlexandraRusina,当你说'd.MyEvent = null;`时,它怎么知道它是一个事件,或者它不是? (14认同)
  • @nawfal不对 - 匿名与Expando不同.您正在创建一个匿名类型,然后无法添加任意属性. (13认同)
  • 第一个块可以使用匿名类型编写:`var expando = new {Address = new {State ="WA"}}; Console.WriteLine(expando.Address.State);`我觉得这个更具可读性但是ymmv.鉴于它是静态类型的,它在这种情况下更有用. (7认同)
  • @ Reed是的,尚未记录ExpandoObject的事件.这个特定的例子实际上出现在博客的讨论中.我稍后可能会将其添加到文档中. (4认同)
  • 这就是 javascript 的生活方式 :) (2认同)

ito*_*son 74

一个优点是绑定方案.数据网格和属性网格将通过TypeDescriptor系统获取动态属性.此外,WPF数据绑定将理解动态属性,因此WPF控件可以比字典更容易绑定到ExpandoObject.

在某些情况下,可能还需要考虑与动态语言的互操作性,这些语言将期望DLR属性而不是字典条目.

  • 它[似乎打破了对动态对象的数据绑定](https://connect.microsoft.com/VisualStudio/feedback/details/522119/databinding-to-dynamic-objects-is-broken).报告用户eisenbergeffect在这里是SO和caliburn.micro的协调员.@AlexandraRusina你可以评论一下bug的状态和状态"Will not fix" (6认同)
  • 对于那些好奇的人,我目前可以使用 WPF4 绑定到 `List&lt;dynamic&gt;` 和 `IEnumerable&lt;dynamic&gt;` (2认同)

小智 44

对我来说真正的好处是来自XAML的完全轻松的数据绑定:

public dynamic SomeData { get; set; }
Run Code Online (Sandbox Code Playgroud)

...

SomeData.WhatEver = "Yo Man!";
Run Code Online (Sandbox Code Playgroud)

...

 <TextBlock Text="{Binding SomeData.WhatEver}" />
Run Code Online (Sandbox Code Playgroud)


Dre*_*rsh 28

基于其他语言的互操作DLR是我能想到的第一个原因.你不能传递它们,Dictionary<string, object>因为它不是IDynamicMetaObjectProvider.另一个额外的好处是,它INotifyPropertyChanged在WPF的数据绑定世界中实现了哪些手段,它还增加了超出Dictionary<K,V>可以提供的功能.


Cha*_*ion 19

这一切都与程序员的便利性有关.我可以想象用这个对象编写快速和脏的程序.

  • @J.亨德里克斯,别忘了他还说"脏".Intellisense有其缺点,但它使调试和错误捕获更容易.我个人仍然喜欢静态而不是动态类型,除非我处理一个奇怪的(并且总是罕见的)情况. (9认同)

gn2*_*n22 14

我认为它会有一个语法上的好处,因为你不再通过使用字典来"伪装"动态添加的属性.

那,并且我会想到与动态语言互操作.


sgn*_*gon 11

这是来自伟大的MSDN文章的例子,该文章关于使用ExpandoObject为传入的结构化数据(即XML,Json)创建动态ad-hoc类型.

我们还可以将委托分配给ExpandoObject的动态属性:

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);
Run Code Online (Sandbox Code Playgroud)

因此,它允许我们在运行时将一些逻辑注入到动态对象中.因此,与lambda表达式,闭包,动态关键字和DynamicObject类一起,我们可以将函数式编程的一些元素引入到我们的C#代码中,我们从动态语言中知道它们就像JavaScript或PHP.