Jakie są prawdziwe zalety ExpandoObject?

Klasa ExpandoObject dodawana do.Net 4 pozwala dowolnie ustawić właściwości obiektu w czasie wykonywania.

Czy są jakieś korzyści z używania Dictionary<string,object>, a może nawet Hashtable ? O ile mi wiadomo, jest to nic innego jak tabela hash, do której można uzyskać dostęp z nieco bardziej zwięzłą składnią.

Na przykład, dlaczego tak jest:

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

Naprawdę lepsze, lub zasadniczo inne, niż:

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

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

Co prawdziwe korzyści uzyskuje się używając ExpandoObject zamiast po prostu używając dowolnego typu słownika, poza tym, że nie jest oczywiste, że używasz typu, który zostanie określony w czasie wykonywania.

Author: Reed Copsey, 2009-10-31

10 answers

Ponieważ napisałem artykuł MSDN, do którego się odnosisz, myślę, że muszę odpowiedzieć na ten.

Po pierwsze, przewidziałem to pytanie i dlatego napisałem post na blogu, który pokazuje mniej lub bardziej rzeczywisty przypadek użycia ExpandoObject: Dynamic in C # 4.0: Introducing the ExpandoObject .

Wkrótce ExpandoObject może pomóc w tworzeniu złożonych obiektów hierarchicznych. Na przykład wyobraź sobie, że masz słownik w słowniku:

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"]);
[[3]} im głębsza jest hierarchia, brzydszy jest kod. Z ExpandoObject pozostaje elegancki i czytelny.
dynamic expando = new ExpandoObject();
expando.Address = new ExpandoObject();
expando.Address.State = "WA";
Console.WriteLine(expando.Address.State);

Po drugie, jak już wspomniano, ExpandoObject implementuje interfejs INotifyPropertyChanged, który daje większą kontrolę nad właściwościami niż słownik.

Wreszcie, możesz dodać zdarzenia do ExpandoObject jak tutaj:

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);
   }
}
 625
Author: Alexandra Rusina,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-12 19:28:41

Jedną z zalet są wiążące scenariusze. Siatki danych i siatki właściwości będą odbierać właściwości dynamiczne za pośrednictwem systemu TypeDescriptor. Ponadto powiązanie danych WPF będzie rozumiało właściwości dynamiczne, więc kontrolki WPF mogą łatwiej wiązać się z obiektem ExpandoObject niż ze słownikiem.

Interoperacyjność z językami dynamicznymi, które oczekują właściwości DLR, a nie wpisów słownikowych, może być również rozważana w niektórych scenariuszach.

 70
Author: itowlson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-31 01:17:31

Prawdziwą korzyścią dla mnie jest całkowicie bezproblemowe powiązanie danych z XAML:

public dynamic SomeData { get; set; }

...

SomeData.WhatEver = "Yo Man!";

...

 <TextBlock Text="{Binding SomeData.WhatEver}" />
 38
Author: bjull,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-01 11:51:40

Interpunkcja z innymi językami bazującymi na DLR jest #1 powodem, o którym myślę. Nie możesz przekazać im Dictionary<string, object>, ponieważ nie jest to IDynamicMetaObjectProvider. Kolejną dodatkową korzyścią jest to, że implementuje INotifyPropertyChanged, co oznacza, że w świecie danych WPF ma również dodatkowe korzyści wykraczające poza to, co może Ci zapewnić Dictionary<K,V>.

 26
Author: Drew Marsh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-23 19:25:45

Chodzi o wygodę programisty. Mogę sobie wyobrazić pisanie szybkich i brudnych programów za pomocą tego obiektu.

 18
Author: ChaosPandion,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-31 01:15:46

Myślę, że będzie to miało korzyści składniowe, ponieważ nie będziesz już "udawał" dynamicznie dodawanych właściwości za pomocą słownika.

To, i interprop z dynamicznymi językami myślę.

 13
Author: gn22,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-31 01:19:57

To przykład z wielkiego artykułu MSDN o używaniu ExpandoObject do tworzenia dynamicznych typów ad-hoc dla przychodzących danych strukturalnych (np.

Możemy również przypisać delegata do dynamicznej właściwościExpandoObject:

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

W ten sposób pozwala nam wprowadzić trochę logiki do dynamicznego obiektu w czasie wykonywania. Dlatego wraz z wyrażeniami lambda, zamknięciami, dynamicznym słowem kluczowym i klasą DynamicObject możemy wprowadzić pewne elementy funkcjonalności programowanie w naszym kodzie C#, który znamy z języków dynamicznych takich jak JavaScript czy PHP.

 9
Author: sgnsajgon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-11 16:17:33

Są przypadki, w których jest to przydatne. Użyję go na przykład do modularnej powłoki. Każdy moduł definiuje własne okno dialogowe konfiguracji z jego ustawieniami. Dostarczam go z ExpandoObject, ponieważ jest to Datacontext i zapisuję wartości w mojej pamięci konfiguracyjnej. W ten sposób Konfigurator dialog writer musi po prostu powiązać z wartością i jest automatycznie tworzony i zapisywany. (I dostarczone do modułu do korzystania z tych ustawień oczywiście)

Jest po prostu łatwiejszy w użyciu niż Słownik. Ale każdy powinien mieć świadomość, że wewnętrznie jest to tylko słownik.

To jest jak LINQ po prostu składniowy cukier, ale to czasem ułatwia sprawę.

Więc odpowiadając bezpośrednio na twoje pytanie: łatwiej jest pisać i łatwiej czytać. Ale technicznie zasadniczo jest to Dictionary<string,object> (Można nawet wrzucić go do jednego, aby wymienić wartości).
 4
Author: n1LWeb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-16 12:17:49
var obj = new Dictionary<string, object>;
...
Console.WriteLine(obj["MyString"]);

Myślę, że to działa tylko dlatego, że wszystko ma ToString (), w przeciwnym razie musiałbyś znać typ, który to był i wrzucić "obiekt" do tego typu.


Niektóre z nich są przydatne częściej niż inne, staram się być dokładna.
  1. O wiele bardziej naturalnym może być dostęp do zbioru, w tym przypadku, który jest faktycznie "słownikiem", używając bardziej bezpośredniej notacji kropkowej.

  2. Wygląda na to, że można to wykorzystać jako naprawdę ładną krotkę. Możesz nadal nazywaj swoich członków "Item1"," Item2 " itp... ale teraz nie musisz, jest również zmienny, w przeciwieństwie do krotki. Ma to ogromną wadę braku wsparcia intellisense.

  3. Możesz czuć się niekomfortowo z "nazwami członków jako ciągami", podobnie jak w przypadku słownika, możesz czuć, że jest to zbyt podobne do "wykonywania ciągów" i może to prowadzić do zakodowania konwencji nazewnictwa i radzenia sobie z pracą z morfemami i sylabami, gdy kod próbuje zrozumieć, jak używać członków :- P

  4. Czy można przypisać wartość do samego ExpandoObject lub tylko jego członków? Porównaj i kontrastuj z dynamic / dynamic [], użyj tego, co najlepiej odpowiada twoim potrzebom.

  5. Nie sądzę, aby dynamic/dynamic[] działało w pętli foreach, trzeba użyć var, ale możliwe, że można użyć ExpandoObject.

  6. Nie możesz używać dynamic jako elementu danych w klasie, być może dlatego, że jest to przynajmniej coś w rodzaju słowa kluczowego, mam nadzieję, że możesz z ExpandoObject.

  7. Spodziewam się, że jest to "ExpandoObject", może być przydatny do oznaczania bardzo ogólnych rzeczy osobno, z kodem, który odróżnia się na podstawie typów, w których jest wiele dynamicznych rzeczy używanych.


Byłoby miło, gdybyś mógł przewiercić kilka poziomów naraz.
var e = new ExpandoObject();
e.position.x = 5;
etc...

To nie jest najlepszy możliwy przykład, wyobraź sobie eleganckie zastosowania odpowiednie we własnych projektach.

Szkoda, że nie możesz mieć kodu zbudowanego niektórych z nich i wcisnąć wyniki do intellisense. Nie jestem pewien,jak to zadziała.

Być miły, jeśli mogą mieć wartość, jak również członków.

var fifteen = new ExpandoObject();
fifteen = 15;
fifteen.tens = 1;
fifteen.units = 5;
fifteen.ToString() = "fifteen";
etc...
 0
Author: alan2here,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-05 18:14:31

Po valueTuples, jaki jest pożytek z klasy ExpandoObject? ten 6-liniowy kod z ExpandoObject:

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

Można zapisać w jednej linii krotkami:

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

Oprócz składni krotki masz silne wnioskowanie typu i wsparcie intlisense

 -1
Author: Eng. M.Hamdy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-22 00:21:28