Depuis que j'ai écrit l'article MSDN auquel vous faites référence, je suppose que je dois répondre à celui-ci.
Tout d'abord, j'ai anticipé cette question et c'est pourquoi j'ai écrit un article de blog qui montre un cas d'utilisation plus ou moins réel pour ExpandoObject: Dynamique en C # 4.0: Présentation de ExpandoObject .
En bref, ExpandoObject peut vous aider à créer des objets hiérarchiques complexes. Par exemple, imaginez que vous avez un dictionnaire dans un dictionnaire:
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"]);
Plus la hiérarchie est profonde, plus le code est laid. Avec ExpandoObject, il reste élégant et lisible.
dynamic expando = new ExpandoObject();
expando.Address = new ExpandoObject();
expando.Address.State = "WA";
Console.WriteLine(expando.Address.State);
Deuxièmement, comme cela a déjà été souligné, ExpandoObject implémente l'interface INotifyPropertyChanged qui vous donne plus de contrôle sur les propriétés qu'un dictionnaire.
Enfin, vous pouvez ajouter des événements à ExpandoObject comme ici:
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);
}
}
Gardez également à l'esprit que rien ne vous empêche d'accepter des arguments d'événement de manière dynamique. En d'autres termes, au lieu d'utiliser EventHandler
, vous pouvez utiliser EventHandler<dynamic>
ce qui entraînerait le deuxième argument du gestionnaire dynamic
.
d.MyEvent = null;
, ou non?var expando = new { Address = new { State = "WA" } }; Console.WriteLine(expando.Address.State);
je trouve cela plus lisible mais ymmv. Et étant donné qu'il est typé statiquement, il est plus utile dans ce contexte.Un avantage est pour les scénarios contraignants. Les grilles de données et les grilles de propriétés récupèrent les propriétés dynamiques via le système TypeDescriptor. En outre, la liaison de données WPF comprendra les propriétés dynamiques, de sorte que les contrôles WPF peuvent se lier à un ExpandoObject plus facilement qu’un dictionnaire.
L'interopérabilité avec les langages dynamiques, qui s'attendra à des propriétés DLR plutôt qu'à des entrées de dictionnaire, peut également être envisagée dans certains scénarios.
la source
List<dynamic>
et de l'IEnumerable<dynamic>
utiliserLe véritable avantage pour moi est la liaison de données sans effort de XAML:
...
...
la source
Interopérez avec d'autres langues fondées sur le
DLR
raison n ° 1 à laquelle je peux penser. Vous ne pouvez pas leur passer unDictionary<string, object>
car ce n'est pas unIDynamicMetaObjectProvider
. Un autre avantage supplémentaire est qu'il implémenteINotifyPropertyChanged
ce qui signifie que dans le monde de la liaison de données de WPF, il a également des avantages supplémentaires au-delà de ce quiDictionary<K,V>
peut vous fournir.la source
Tout est question de commodité pour les programmeurs. Je peux imaginer écrire des programmes rapides et sales avec cet objet.
la source
Je pense que cela aura un avantage syntaxique, car vous ne serez plus en train de "simuler" des propriétés ajoutées dynamiquement en utilisant un dictionnaire.
Cela, et interagir avec des langues dynamiques, je pense.
la source
C'est un exemple d'un excellent article MSDN sur l'utilisation d' ExpandoObject pour créer des types ad hoc dynamiques pour les données structurées entrantes (c'est-à-dire XML, Json).
Nous pouvons également affecter un délégué à la propriété dynamique d' ExpandoObject :
Ainsi, il nous permet d'injecter de la logique dans un objet dynamique lors de l'exécution. Par conséquent, avec les expressions lambda, les fermetures, les mots clés dynamiques et la classe DynamicObject , nous pouvons introduire certains éléments de programmation fonctionnelle dans notre code C #, que nous connaissons des langages dynamiques comme JavaScript ou PHP.
la source
Il y a des cas où cela est pratique. Je vais l'utiliser pour un shell modularisé par exemple. Chaque module définit sa propre boîte de dialogue de configuration liée à ses paramètres. Je lui fournis un ExpandoObject car c'est Datacontext et enregistre les valeurs dans ma configuration Storage. De cette façon, le rédacteur de la boîte de dialogue de configuration n'a qu'à se lier à une valeur et il est automatiquement créé et enregistré. (Et fourni au module pour utiliser ces paramètres bien sûr)
Il est tout simplement plus facile à utiliser qu'un dictionnaire. Mais tout le monde doit savoir qu'en interne, il ne s'agit que d'un dictionnaire.
C'est comme LINQ juste du sucre syntaxique, mais cela facilite parfois les choses.
Donc, pour répondre directement à votre question: il est plus facile d'écrire et de lire. Mais techniquement, c'est essentiellement un
Dictionary<string,object>
(vous pouvez même le fondre en un pour répertorier les valeurs).la source
Je pense que cela ne fonctionne que parce que tout a un ToString (), sinon il faudrait connaître le type qu'il était et transtyper l '«objet» sur ce type.
Certains d'entre eux sont utiles plus souvent que d'autres, j'essaie d'être minutieux.
Il peut être beaucoup plus naturel d'accéder à une collection, dans ce cas ce qui est en fait un "dictionnaire", en utilisant la notation par points plus directe.
Il semble que cela puisse être utilisé comme un tuple vraiment sympa. Vous pouvez toujours appeler vos membres "Item1", "Item2" etc ... mais maintenant vous n'avez plus à le faire, il est également modifiable, contrairement à un Tuple. Cela présente l'énorme inconvénient du manque de support intellisense.
Vous pouvez être mal à l'aise avec les «noms de membres sous forme de chaînes», comme c'est le cas avec le dictionnaire, vous pouvez penser que c'est trop comme «exécuter des chaînes», et cela peut conduire à des conventions de dénomination codées et à traiter avec des morphèmes et syllabes lorsque le code essaie de comprendre comment utiliser les membres :-P
Pouvez-vous attribuer une valeur à un ExpandoObject lui-même ou simplement à ses membres? Comparez et contrastez avec dynamique / dynamique [], utilisez celui qui convient le mieux à vos besoins.
Je ne pense pas que dynamic / dynamic [] fonctionne dans une boucle foreach, vous devez utiliser var, mais vous pouvez peut-être utiliser ExpandoObject.
Vous ne pouvez pas utiliser dynamic comme membre de données dans une classe, peut-être parce que c'est au moins un peu comme un mot-clé, espérons-le, vous pouvez le faire avec ExpandoObject.
Je m'attends à ce qu'il "soit" un ExpandoObject, pourrait être utile pour étiqueter des choses très génériques, avec du code qui différencie en fonction des types où il y a beaucoup de choses dynamiques utilisées.
Soyez gentil si vous pouviez explorer plusieurs niveaux à la fois.
Ce n'est pas le meilleur exemple possible, imaginez des utilisations élégantes appropriées à vos propres projets.
C'est dommage que vous ne puissiez pas avoir du code pour en construire et pousser les résultats vers intellisense. Je ne sais pas comment cela fonctionnerait cependant.
Soyez gentils s'ils pouvaient avoir une valeur aussi bien que les membres.
la source
Après valueTuples, à quoi sert la classe ExpandoObject? ce code de 6 lignes avec ExpandoObject:
peut être écrit sur une ligne avec des tuples:
outre la syntaxe de tuple, vous avez une forte inférence de type et une prise en charge intelligente
la source