Program Tip

ExpandoObject의 진정한 이점은 무엇입니까?

programtip 2020. 10. 3. 11:32
반응형

ExpandoObject의 진정한 이점은 무엇입니까?


ExpandoObject의 클래스는 런타임시 객체에 .NET 4 임의로 설정 속성 수에 추가.

Dictionary<string, object>, 또는 실제로 해시 테이블 을 사용하는 것보다 이점이 있습니까? 내가 알 수있는 한, 이것은 약간 더 간결한 구문으로 액세스 할 수있는 해시 테이블에 지나지 않습니다.

예를 들어, 이유는 다음과 같습니다.

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를 사용하는 대신에 당신이 런타임에 결정 될 것 유형을 사용하고 있는지 명백한되지 않는 이외의 임의의 사전 유형을 사용하여 얻을 수 있습니다.


내가 언급 한 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);
   }
}

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.

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


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

public dynamic SomeData { get; set; }

...

SomeData.WhatEver = "Yo Man!";

...

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

Interop with other languages founded on the DLR is #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 INotifyPropertyChanged which means in the databinding world of WPF it also has added benefits beyond what Dictionary<K,V> can provide you.


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


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.


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

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

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.


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)

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.

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


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.


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.


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...

After valueTuples, what's the use of ExpandoObject class? this 6 lines code with 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

참고URL : https://stackoverflow.com/questions/1653046/what-are-the-true-benefits-of-expandoobject

반응형