代码之家  ›  专栏  ›  技术社区  ›  Reed Copsey

Expandoobject的真正好处是什么?

  •  542
  • Reed Copsey  · 技术社区  · 14 年前

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

    与使用 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而不仅仅是使用任意的字典类型,除了不明显您使用的是将在运行时确定的类型之外,还可以获得一些优势。

    10 回复  |  直到 5 年前
        1
  •  645
  •   Uwe Keim Chand    5 年前

    既然我写了你所指的msdn文章,我想我必须回答这个问题。

    首先,我预料到了这个问题,这就是为什么我写了一篇博客文章,展示了Expandoobject的一个或多或少真实的用例: Dynamic in C# 4.0: Introducing the 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"]);
    

    层次结构越深,代码越难看。通过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);
       }
    }
    
        2
  •  74
  •   itowlson    14 年前

    一个优点是绑定场景。数据网格和属性网格将通过typescriptor系统获取动态属性。此外,WPF数据绑定将了解动态属性,因此WPF控件比字典更容易绑定到Expandoobject。

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

        3
  •  41
  •   bjull    13 年前

    对我来说,真正的好处是XAML完全可以轻松地进行数据绑定:

    public dynamic SomeData { get; set; }
    

    SomeData.WhatEver = "Yo Man!";
    

     <TextBlock Text="{Binding SomeData.WhatEver}" />
    
        4
  •  27
  •   Soner Gönül    12 年前

    与基于 DLR 是我能想到的原因之一。你不能超过他们 Dictionary<string, object> 因为它不是一个 IDynamicMetaObjectProvider . 另一个额外的好处是它实现了 INotifyPropertyChanged 这意味着在WPF的数据绑定世界中,除了 Dictionary<K,V> 可以提供给你。

        5
  •  19
  •   ChaosPandion    14 年前

    这都是为了程序员的方便。我可以想象用这个对象编写快速而脏的程序。

        6
  •  14
  •   gn22    14 年前

    我认为它将有一个句法上的好处,因为您将不再使用字典来“伪造”动态添加的属性。

    我认为,它可以与动态语言互操作。

        7
  •  9
  •   Auzi    7 年前

    很好的例子 MSDN article 关于使用 扩展对象 用于为传入的结构化数据(即XML、JSON)创建动态即席类型。

    我们也可以将代表分配给 扩展对象 的动态属性:

    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 class 我们可以在C代码中引入一些函数式编程的元素,这是我们从动态语言如javascript或php中了解到的。

        8
  •  4
  •   bluish dmajkic    11 年前

    有些情况下这很方便。例如,我将把它用于模块化的shell。每个模块定义它自己的配置对话框数据绑定到它的设置中。我为它提供了一个expandoobject作为dataContext,并将值保存在我的配置存储中。这样,配置对话框编写器只需绑定到一个值,它就会自动创建和保存。(并提供给模块使用这些设置)

    它比字典更容易使用。但每个人都应该知道,在内部,它只是一本字典。

    它就像LINQ只是句法上的糖分,但有时会让事情变得更容易。

    所以直接回答你的问题:写起来容易,读起来也容易。但从技术上讲,它本质上是 Dictionary<string,object> (您甚至可以将其转换为一个值来列出值)。

        9
  •  -1
  •   alan2here    8 年前
    var obj = new Dictionary<string, object>;
    ...
    Console.WriteLine(obj["MyString"]);
    

    我认为这只会起作用,因为每件事都有一个toString(),否则你必须知道它是什么类型,并将“object”强制转换为那个类型。


    其中一些比其他的更有用,我正在努力彻底。

    1. 使用更直接的点表示法访问集合可能更自然,在本例中,什么是有效的“字典”。

    2. 这似乎可以用作一个非常好的元组。你仍然可以称你的成员为“项目1”、“项目2”等…但是现在你不需要了,它也是可变的,不像元组。这确实存在缺乏智能感知支持的巨大缺点。

    3. 你可能会对“成员名作为字符串”感到不舒服,就像字典的感觉一样,你可能会觉得它太像“执行字符串”,它可能会导致命名约定被编码,并在代码试图理解如何使用成员时处理语素和音节。

    4. 可以将值赋给Expandoobject本身或只是它的成员吗?与动态/动态[]进行比较和对比,使用最适合您需要的工具。

    5. 我认为dynamic/dynamic[]在foreach循环中不起作用,您必须使用var,但可能可以使用expandoobject。

    6. 不能在类中使用dynamic作为数据成员,可能是因为它至少有点像关键字,希望您可以使用expandoobject。

    7. 我希望它“是”一个expandoobject,可能有助于将非常普通的事物分开,代码根据使用了大量动态事物的类型进行区分。


    如果你能一次钻取多个层面,那就太好了。

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

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

    很遗憾,您不能让代码构建其中的一些,并将结果推送到IntelliSense。不过,我不确定这会如何运作。

    如果他们既有成员又有价值,那就好了。

    var fifteen = new ExpandoObject();
    fifteen = 15;
    fifteen.tens = 1;
    fifteen.units = 5;
    fifteen.ToString() = "fifteen";
    etc...
    
        10
  •  -2
  •   Eng. M.Hamdy    6 年前

    在valuetuples之后,expandoobject类的用途是什么? 这6行代码使用expandoobject:

    dynamic T = new ExpandoObject();
    T.x = 1;
    T.y = 2;
    T.z = new ExpandoObject();
    T.z.a = 3;
    T.b= 4;
    

    可以用元组在一行中写入:

    var T = (x: 1, y: 2, z: (a: 3, b: 4));
    

    除了元组语法之外,您还具有强大的类型推断和intlisense支持。