C# ExpandoObject 的真正好处是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1653046/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 19:42:30  来源:igfitidea点击:

What are the true benefits of ExpandoObject?

c#.net.net-4.0c#-4.0

提问by Reed Copsey

The ExpandoObjectclass being added to .NET 4 allows you to arbitrarily set properties onto an object at runtime.

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

Are there any advantages to this over using a Dictionary<string, object>, or really even a Hashtable? As far as I can tell, this is nothing but a hash table that you can access with slightly more succinct syntax.

与使用HashtableDictionary<string, object>甚至Hashtable相比,这有什么优势吗?据我所知,这只不过是一个哈希表,您可以使用更简洁的语法访问它。

For example, why is this:

例如,这是为什么:

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

Really better, or substantially different, than:

确实比:

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

Console.WriteLine(obj["MyString"]);

What realadvantages are gained by using ExpandoObject instead of just using an arbitrary dictionary type, other than not being obvious that you're using a type that's going to be determined at runtime.

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

采纳答案by Alexandra Rusina

Since I wrote the MSDN article you are referring to, I guess I have to answer this one.

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

First, I anticipated this question and that's why I wrote a blog post that shows a more or less real use case for ExpandoObject: Dynamic in C# 4.0: Introducing the ExpandoObject.

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

Shortly, ExpandoObject can help you create complex hierarchical objects. For example, imagine that you have a dictionary within a dictionary:

很快,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"]);

The deeper is the hierarchy, the uglier is the code. With ExpandoObject it stays elegant and readable.

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

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

Second, as it was already pointed out, ExpandoObject implements INotifyPropertyChanged interface which gives you more control over properties than a dictionary.

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

Finally, you can add events to ExpandoObject like here:

最后,您可以像这样向 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;

       e?.Invoke(d, new EventArgs());
   }

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

Also, keep in mind that nothing is preventing you from accepting event arguments in a dynamic way. In other words, instead of using EventHandler, you can use EventHandler<dynamic>which would cause the second argument of the handler to be dynamic.

另外,请记住,没有什么可以阻止您以动态方式接受事件参数。换句话说,EventHandler您可以使用EventHandler<dynamic>which 将导致处理程序的第二个参数为,而不是使用dynamic

回答by ChaosPandion

It's all about programmer convenience. I can imagine writing quick and dirty programs with this object.

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

回答by itowlson

One advantage is for binding scenarios. Data grids and property grids will pick up the dynamic properties via the TypeDescriptor system. In addition, WPF data binding will understand dynamic properties, so WPF controls can bind to an ExpandoObject more readily than a dictionary.

优势之一是用于绑定场景。数据网格和属性网格将通过 TypeDescriptor 系统获取动态属性。此外,WPF 数据绑定将理解动态属性,因此 WPF 控件可以比字典更容易绑定到 ExpandoObject。

Interoperability with dynamic languages, which will be expecting DLR properties rather than dictionary entries, may also be a consideration in some scenarios.

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

回答by Drew Marsh

Interop with other languages founded on the DLRis #1 reason I can think of. You can't pass them a Dictionary<string, object>as it's not an IDynamicMetaObjectProvider. Another added benefit is that it implements INotifyPropertyChangedwhich means in the databinding world of WPF it also has added benefits beyond what Dictionary<K,V>can provide you.

与其他语言的互操作DLR是我能想到的第一个原因。您不能通过它们 aDictionary<string, object>因为它不是IDynamicMetaObjectProvider. 另一个额外的好处是它实现了INotifyPropertyChanged这意味着在 WPF 的数据绑定世界中,它还具有超出Dictionary<K,V>您所能提供的额外好处。

回答by gn22

I think it will have a syntactic benefit, since you'll no longer be "faking" dynamically added properties by using a dictionary.

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

That, and interop with dynamic languages I would think.

那,以及我认为与动态语言的互操作。

回答by bjull

The real benefit for me is the totally effortless data binding from XAML:

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

public dynamic SomeData { get; set; }

...

...

SomeData.WhatEver = "Yo Man!";

...

...

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

回答by n1LWeb

There are some cases where this is handy. I'll use it for a Modularized shell for instance. Each module defines it's own Configuration Dialog databinded to it's settings. I provide it with an ExpandoObject as it's Datacontext and save the values in my configuration Storage. This way the Configuration Dialog writer just has to Bind to a Value and it's automatically created and saved. (And provided to the module for using these settings of course)

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

It' simply easier to use than an Dictionary. But everyone should be aware that internally it is just a Dictionary.

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

It's like LINQ just syntactic sugar, but it makes things easier sometimes.

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

So to answer your question directly: It's easier to write and easier to read. But technically it essentially is a Dictionary<string,object>(You can even cast it into one to list the values).

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

回答by sgnsajgon

It's example from great MSDN articleabout using ExpandoObjectfor creating dynamic ad-hoc types for incoming structured data (i.e XML, Json).

这是MSDN 文章中关于使用ExpandoObject为传入的结构化数据(即 XML、Json)创建动态临时类型的示例。

We can also assign delegate to ExpandoObject's dynamic property:

我们还可以将委托分配给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);

Thus it allows us to inject some logic into dynamic object at runtime. Therefore, together with lambda expressions, closures, dynamic keyword and DynamicObject class, we can introduce some elements of functional programming into our C# code, which we knows from dynamic languages as like JavaScript or PHP.

因此它允许我们在运行时将一些逻辑注入到动态对象中。因此,结合 lambda 表达式、闭包、动态关键字和DynamicObject 类,我们可以将函数式编程的一些元素引入到我们的 C# 代码中,这些元素是我们从 JavaScript 或 PHP 等动态语言中了解到的。

回答by alan2here

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

I think that only works because everything has a ToString(), otherwise you'd have to know the type that it was and cast the 'object' to that type.

我认为这只有效,因为一切都有一个 ToString(),否则您必须知道它的类型并将“对象”转换为该类型。



Some of these are useful more often than others, I'm trying to be thorough.

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

  1. It may be far more natural to access a collection, in this case what is effectively a "dictionary", using the more direct dot notation.

  2. It seems as if this could be used as a really nice Tuple. You can still call your members "Item1", "Item2" etc... but now you don't have to, it's also mutable, unlike a Tuple. This does have the huge drawback of lack of intellisense support.

  3. You may be uncomfortable with "member names as strings", as is the feel with the dictionary, you may feel it is too like "executing strings", and it may lead to naming conventions getting coded in, and dealing with working with morphemes and syllables when code is trying understand how to use members :-P

  4. Can you assign a value to an ExpandoObject itself or just it's members? Compare and contrast with dynamic/dynamic[], use whichever best suits your needs.

  5. I don't think dynamic/dynamic[] works in a foreach loop, you have to use var, but possibly you can use ExpandoObject.

  6. You cannot use dynamic as a data member in a class, perhaps because it's at least sort of like a keyword, hopefully you can with ExpandoObject.

  7. I expect it "is" an ExpandoObject, might be useful to label very generic things apart, with code that differentiates based on types where there is lots of dynamic stuff being used.

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

  2. 似乎这可以用作一个非常好的元组。您仍然可以称您的成员为“Item1”、“Item2”等……但现在您不必这样做了,它也是可变的,与元组不同。这确实具有缺乏智能感知支持的巨大缺点。

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

  4. 您可以为 ExpandoObject 本身或仅为其成员分配值吗?与 dynamic/dynamic[] 进行比较和对比,使用最适合您需求的那个。

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

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

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



Be nice if you could drill down multiple levels at once.

如果您可以一次深入研究多个级别,那就太好了。

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

Thats not the best possible example, imagine elegant uses as appropriate in your own projects.

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

It's a shame you cannot have code build some of these and push the results to intellisense. I'm not sure how this would work though.

很遗憾你不能让代码构建其中的一些并将结果推送到智能感知。我不确定这将如何工作。

Be nice if they could have a value as well as members.

如果他们能像会员一样有价值,那就太好了。

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

回答by Eng. M.Hamdy

After valueTuples, what's the use of ExpandoObject class? this 6 lines code with ExpandoObject:

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

can be written in one line with tuples:

可以用元组写在一行中:

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

besides with tuple syntax you have strong type inference and intlisense support

除了元组语法,您还拥有强大的类型推断和智能感知支持