Da ich den MSDN-Artikel geschrieben habe, auf den Sie sich beziehen, muss ich diesen wohl beantworten.
Zuerst habe ich diese Frage vorweggenommen und deshalb einen Blog-Beitrag geschrieben, der einen mehr oder weniger realen Anwendungsfall für ExpandoObject: Dynamic in C # 4.0: Einführung des ExpandoObject zeigt .
In Kürze kann ExpandoObject Ihnen beim Erstellen komplexer hierarchischer Objekte helfen. Stellen Sie sich zum Beispiel vor, Sie haben ein Wörterbuch in einem Wörterbuch:
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"]);
Je tiefer die Hierarchie ist, desto hässlicher ist der Code. Mit ExpandoObject bleibt es elegant und lesbar.
dynamic expando = new ExpandoObject();
expando.Address = new ExpandoObject();
expando.Address.State = "WA";
Console.WriteLine(expando.Address.State);
Zweitens implementiert ExpandoObject, wie bereits erwähnt, die INotifyPropertyChanged-Schnittstelle, mit der Sie mehr Kontrolle über Eigenschaften haben als mit einem Wörterbuch.
Schließlich können Sie ExpandoObject wie folgt Ereignisse hinzufügen:
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);
}
}
Denken Sie auch daran, dass Sie nichts daran hindert, Ereignisargumente dynamisch zu akzeptieren. Mit anderen Worten, anstatt zu verwenden EventHandler
, können Sie verwenden, EventHandler<dynamic>
was dazu führen würde, dass das zweite Argument des Handlers lautet dynamic
.
d.MyEvent = null;
, oder nicht?var expando = new { Address = new { State = "WA" } }; Console.WriteLine(expando.Address.State);
Ich finde das besser lesbar, aber ymmv. Und da es statisch typisiert ist, ist es in diesem Zusammenhang nützlicher.Ein Vorteil ist für Bindungsszenarien. Datenraster und Eigenschaftsraster erfassen die dynamischen Eigenschaften über das TypeDescriptor-System. Darüber hinaus versteht die WPF-Datenbindung dynamische Eigenschaften, sodass WPF-Steuerelemente leichter an ein ExpandoObject als an ein Wörterbuch gebunden werden können.
In einigen Szenarien kann auch die Interoperabilität mit dynamischen Sprachen in Betracht gezogen werden, bei der DLR-Eigenschaften anstelle von Wörterbucheinträgen erwartet werden.
quelle
List<dynamic>
IEnumerable<dynamic>
Der eigentliche Vorteil für mich ist die völlig mühelose Datenbindung von XAML:
...
...
quelle
Interop mit anderen Sprachen, die auf dem
DLR
Grund basieren, den ich mir vorstellen kann. Sie können sie nicht weitergeben,Dictionary<string, object>
da es keine istIDynamicMetaObjectProvider
. Ein weiterer zusätzlicher Vorteil ist die Implementierung,INotifyPropertyChanged
was bedeutet, dass es in der Datenbindungswelt von WPF auch zusätzliche VorteileDictionary<K,V>
bietet, die über das hinausgehen, was Sie bieten können.quelle
Es geht um Programmierkomfort. Ich kann mir vorstellen, mit diesem Objekt schnelle und schmutzige Programme zu schreiben.
quelle
Ich denke, es wird einen syntaktischen Vorteil haben, da Sie mithilfe eines Wörterbuchs keine dynamisch hinzugefügten Eigenschaften mehr "vortäuschen".
Das und Interop mit dynamischen Sprachen würde ich denken.
quelle
Es ist ein Beispiel aus einem großartigen MSDN-Artikel über die Verwendung von ExpandoObject zum Erstellen dynamischer Ad-hoc-Typen für eingehende strukturierte Daten (z. B. XML, Json).
Wir können der dynamischen Eigenschaft von ExpandoObject auch einen Delegaten zuweisen :
Auf diese Weise können wir zur Laufzeit eine Logik in ein dynamisches Objekt einfügen. Daher können wir zusammen mit Lambda-Ausdrücken, Abschlüssen, dynamischen Schlüsselwörtern und der DynamicObject-Klasse einige Elemente der funktionalen Programmierung in unseren C # -Code einführen, die wir aus dynamischen Sprachen wie JavaScript oder PHP kennen.
quelle
In einigen Fällen ist dies praktisch. Ich werde es zum Beispiel für eine modularisierte Shell verwenden. Jedes Modul definiert seinen eigenen Konfigurationsdialog, der an seine Einstellungen gebunden ist. Ich versorge es mit einem ExpandoObject als Datacontext und speichere die Werte in meinem Konfigurationsspeicher. Auf diese Weise muss der Konfigurationsdialogschreiber nur an einen Wert binden und wird automatisch erstellt und gespeichert. (Und natürlich dem Modul zur Verfügung gestellt, um diese Einstellungen zu verwenden)
Es ist einfach einfacher zu bedienen als ein Wörterbuch. Aber jeder sollte sich bewusst sein, dass es intern nur ein Wörterbuch ist.
Es ist wie LINQ nur syntaktischer Zucker, aber es macht die Dinge manchmal einfacher.
Um Ihre Frage direkt zu beantworten: Es ist einfacher zu schreiben und leichter zu lesen. Aber technisch gesehen ist es im Wesentlichen ein
Dictionary<string,object>
(Sie können es sogar in einen umwandeln, um die Werte aufzulisten).quelle
Ich denke, das funktioniert nur, weil alles einen ToString () hat, sonst müsste man den Typ kennen, der es war, und das 'Objekt' in diesen Typ umwandeln.
Einige davon sind öfter nützlich als andere, ich versuche gründlich zu sein.
Es kann weitaus natürlicher sein, mit der direkteren Punktnotation auf eine Sammlung zuzugreifen, in diesem Fall auf ein "Wörterbuch".
Es scheint, als könnte dies als ein wirklich schönes Tupel verwendet werden. Sie können Ihre Mitglieder weiterhin "Item1", "Item2" usw. nennen, aber jetzt müssen Sie nicht mehr, es ist im Gegensatz zu einem Tupel auch veränderlich. Dies hat den großen Nachteil, dass es an Intellisense-Unterstützung mangelt.
Es kann sein, dass Sie sich mit "Mitgliedsnamen als Zeichenfolgen" nicht wohl fühlen, ebenso wie mit dem Wörterbuch. Sie haben möglicherweise das Gefühl, dass es zu ähnlich ist wie "Ausführen von Zeichenfolgen", und es kann dazu führen, dass Namenskonventionen codiert werden und mit Morphemen und Morphemen gearbeitet wird Silben, wenn Code versucht zu verstehen, wie man Mitglieder verwendet :-P
Können Sie einem ExpandoObject selbst oder nur seinen Mitgliedern einen Wert zuweisen? Vergleichen und kontrastieren Sie mit dynamic / dynamic [] und verwenden Sie das, was Ihren Anforderungen am besten entspricht.
Ich denke nicht, dass dynamic / dynamic [] in einer foreach-Schleife funktioniert. Sie müssen var verwenden, aber möglicherweise können Sie ExpandoObject verwenden.
Sie können dynamic nicht als Datenelement in einer Klasse verwenden, vielleicht weil es zumindest wie ein Schlüsselwort ist, hoffentlich mit ExpandoObject.
Ich gehe davon aus, dass es sich um ein ExpandoObject handelt, das nützlich sein kann, um sehr allgemeine Dinge mit Code zu kennzeichnen, der sich nach Typen unterscheidet, bei denen viele dynamische Dinge verwendet werden.
Seien Sie nett, wenn Sie mehrere Ebenen gleichzeitig aufschlüsseln könnten.
Das ist nicht das bestmögliche Beispiel. Stellen Sie sich elegante Anwendungen vor, die in Ihren eigenen Projekten angemessen sind.
Es ist eine Schande, dass Sie nicht einige davon Code erstellen lassen und die Ergebnisse auf Intellisense übertragen können. Ich bin mir nicht sicher, wie das funktionieren würde.
Sei nett, wenn sie einen Wert haben könnten, genauso wie Mitglieder.
quelle
Was nützt die ExpandoObject-Klasse nach valueTuples? Dieser 6-Zeilen-Code mit ExpandoObject:
kann in einer Zeile mit Tupeln geschrieben werden:
Außerdem haben Sie mit der Tupel-Syntax eine starke Typinferenz und Intlisense-Unterstützung
quelle