Ponieważ napisałem artykuł MSDN, o którym mówisz, chyba muszę na to odpowiedzieć.
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 w C # 4.0: Przedstawiamy ExpandoObject .
Krótko mówiąc, 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"]);
Im głębsza jest hierarchia, tym bardziej brzydki jest kod. Dzięki 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.
Na koniec 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;
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);
}
}
Pamiętaj też, że nic nie stoi na przeszkodzie, aby przyjmować argumenty zdarzeń w sposób dynamiczny. Innymi słowy, zamiast używać EventHandler
możesz użyć, EventHandler<dynamic>
co spowodowałoby, że byłby to drugi argument programu obsługi dynamic
.
d.MyEvent = null;
, czy nie?var expando = new { Address = new { State = "WA" } }; Console.WriteLine(expando.Address.State);
uważam to za bardziej czytelne, ale ymmv. Biorąc pod uwagę, że jest on wpisany statycznie, jest bardziej przydatny w tym kontekście.Jedną zaletą są wiążące scenariusze. Siatki danych i siatki właściwości będą pobierać właściwości dynamiczne za pośrednictwem systemu TypeDescriptor. Ponadto powiązanie danych WPF zrozumie właściwości dynamiczne, więc formanty WPF mogą łatwiej powiązać obiekt ExpandoObject niż słownik.
Współdziałanie z dynamicznymi językami, które będą oczekiwać właściwości DLR zamiast wpisów słownika, może również być rozważane w niektórych scenariuszach.
źródło
List<dynamic>
iIEnumerable<dynamic>
używać WPF4Prawdziwą korzyścią dla mnie jest całkowicie łatwe wiązanie danych od XAML:
...
...
źródło
Interakcja z innymi językami oparta
DLR
jest na pierwszym miejscu, o którym mogę myśleć. Nie możesz ich przekazać,Dictionary<string, object>
bo to nie jestIDynamicMetaObjectProvider
. Kolejną dodatkową zaletą jest to, że implementuje,INotifyPropertyChanged
co oznacza, że w świecie WPF w zakresie wiązania danych ma także dodatkowe zalety, które nieDictionary<K,V>
są w stanie zapewnić.źródło
Chodzi o wygodę programisty. Mogę sobie wyobrazić pisanie szybkich i brudnych programów z tym obiektem.
źródło
Myślę, że przyniesie to korzyści składniowe, ponieważ nie będziesz już „fałszował” dynamicznie dodawanych właściwości za pomocą słownika.
Myślę, że i interakcja z dynamicznymi językami.
źródło
Jest to przykład świetnego artykułu MSDN na temat używania ExpandoObject do tworzenia dynamicznych typów ad-hoc dla przychodzących danych strukturalnych (np. XML, Json).
Możemy również przypisać delegata do właściwości dynamicznej ExpandoObject :
Dzięki temu możemy wprowadzić logikę do obiektu dynamicznego w czasie wykonywania. Dlatego wraz z wyrażeniami lambda, zamknięciami, słowem kluczowym dynamicznym i klasą DynamicObject możemy wprowadzić pewne elementy programowania funkcjonalnego do naszego kodu C #, który znamy z języków dynamicznych, takich jak JavaScript lub PHP.
źródło
W niektórych przypadkach jest to przydatne. Użyję go na przykład do powłoki modułowej. Każdy moduł definiuje własne okno dialogowe Konfiguracja powiązane z jego ustawieniami. Dostarczam mu ExpandoObject, ponieważ jest to tekst danych i zapisuję wartości w mojej konfiguracji Storage. W ten sposób moduł zapisujący okno dialogowe konfiguracji musi po prostu powiązać się z wartością, która zostanie automatycznie utworzona i zapisana. (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 cukier syntaktyczny LINQ, ale czasem to ułatwia.
Aby odpowiedzieć bezpośrednio na pytanie: łatwiej jest pisać i czytać. Ale technicznie zasadniczo jest to
Dictionary<string,object>
(Możesz nawet rzucić go w jedno, aby wyświetlić wartości).źródło
Myślę, że to działa tylko dlatego, że wszystko ma funkcję ToString (), w przeciwnym razie musisz znać typ, który był, i rzutować „obiekt” na ten typ.
Niektóre z nich są przydatne częściej niż inne, staram się być dokładny.
Dostęp do kolekcji może być znacznie bardziej naturalny, w tym przypadku jest to „słownik”, przy użyciu bardziej bezpośredniej notacji kropkowej.
Wygląda na to, że można to wykorzystać jako naprawdę niezłą Tuple. Nadal możesz nazywać swoich członków „Przedmiotem 1”, „Przedmiotem 2” itd. ... ale teraz nie musisz, jest to również zmienne, w przeciwieństwie do Tuple. Ma to ogromną wadę polegającą na braku wsparcia dla technologii Intellisense.
Możesz czuć się niekomfortowo z „nazwami członków jako ciągami”, podobnie jak w przypadku słownika, możesz poczuć, że jest to zbyt podobne do „wykonywania ciągów” i może prowadzić do zakodowania konwencji nazewnictwa i radzenia sobie z pracą z morfemami i sylaby, gdy kod próbuje zrozumieć, jak używać członków :-P
Czy możesz przypisać wartość do samego ExpandoObject lub tylko do jego członków? Porównaj i kontrastuj z dynamicznym / dynamicznym [], użyj tych, które najlepiej odpowiadają Twoim potrzebom.
Nie sądzę, żeby dynamiczny / dynamiczny [] działał w pętli foreach, musisz użyć var, ale prawdopodobnie możesz użyć ExpandoObject.
Nie możesz używać dynamiki jako elementu danych w klasie, być może dlatego, że jest to coś w rodzaju słowa kluczowego, mam nadzieję, że możesz to zrobić dzięki ExpandoObject.
Spodziewam się, że „jest” ExpandoObject, może być użyteczne do oznaczania bardzo ogólnych rzeczy osobno, z kodem, który różnicuje się w zależności od typów, w których używa się wielu dynamicznych rzeczy.
Bądź miły, jeśli możesz przejść wiele poziomów jednocześnie.
To nie jest najlepszy możliwy przykład, wyobraź sobie eleganckie zastosowania odpowiednie we własnych projektach.
Szkoda, że niektóre z nich nie mogą zbudować kodu i przesunąć wyniki na inteligencję. Nie jestem jednak pewien, jak to by działało.
Bądź miły, jeśli mogą mieć wartość tak samo jak członkowie.
źródło
Po valueTuples do czego służy klasa ExpandoObject? ten 6-liniowy kod z ExpandoObject:
można zapisać w jednym wierszu z krotkami:
oprócz składni krotek masz silne wnioskowanie o typie i wsparcie intlisense
źródło