Question

La ExpandoObject est une classe. être ajouté à .NET 4 vous permet de définir arbitrairement des propriétés sur un objet au moment de l'exécution.

Cela présente-t-il des avantages par rapport à l'utilisation d'un Dictionary<string, object> ou même un Hashtable ? Pour autant que je sache, il ne s'agit que d'une table de hachage à laquelle vous pouvez accéder avec une syntaxe légèrement plus succincte.

Par exemple, pourquoi est-ce:

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

Vraiment meilleur ou substantiellement différent de:

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

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

Quels sont les réels avantages à utiliser ExpandoObject au lieu d'utiliser simplement un type de dictionnaire arbitraire, sinon que le fait que vous utilisez un type qui sera déterminé à l'exécution n'est pas évident.

Était-ce utile?

La solution

Depuis que j'ai écrit l'article MSDN auquel vous faites référence, je suppose que je dois répondre à celui-ci.

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 .

Rapidement, 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 permet de mieux contrôler 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;

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

Autres conseils

Un des avantages réside dans les scénarios de liaison. Les grilles de données et les grilles de propriétés captureront les propriétés dynamiques via le système TypeDescriptor. De plus, la liaison de données WPF comprendra les propriétés dynamiques, ainsi les contrôles WPF peuvent se lier à un objet ExpandoObject plus facilement qu’un dictionnaire.

L’interopérabilité avec les langages dynamiques, qui attendront des propriétés DLR plutôt que des entrées de dictionnaire, peut également être prise en compte dans certains scénarios.

Le véritable avantage pour moi est la liaison de données sans effort de XAML:

public dynamic SomeData { get; set; }

...

SomeData.WhatEver = "Yo Man!";

...

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

Interopérer avec d’autres langues fondées sur la DLR est la raison n ° 1 à laquelle je peux penser. Vous ne pouvez pas leur passer un Dictionary<string, object> car ce n'est pas un IDynamicMetaObjectProvider. Un autre avantage supplémentaire est le fait qu'il implémente INotifyPropertyChanged ce qui signifie que, dans le monde des liaisons de données de WPF, il présente également des avantages supplémentaires au-delà de ce que Dictionary<K,V> peut vous offrir.

Tout est une question de commodité pour les programmeurs. Je peux imaginer écrire des programmes rapides et sales avec cet objet.

Je pense que cela aura un avantage syntaxique, puisque vous ne serez plus " fake " ajouter dynamiquement des propriétés à l'aide d'un dictionnaire.

Cela et l’interopérabilité avec des langages dynamiques, je pense.

C’est un exemple tiré du superbe article MSDN sur l'utilisation de ExpandoObject pour la création de types ad hoc dynamiques pour les données structurées entrantes (XML, Json, par exemple).

Nous pouvons également affecter un délégué à la propriété dynamique de ExpandoObject :

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

Cela nous permet donc d’injecter de la logique dans un objet dynamique au moment de l’exécution. Par conséquent, avec les expressions lambda, les fermetures, le mot clé dynamique et classe DynamicObject , nous pouvons introduire des éléments de programmation fonctionnelle dans notre code C #, que nous connaissons dans les langages dynamiques tels que JavaScript ou PHP.

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 base de données de dialogue de configuration avec ses paramètres. Je lui fournis un ExpandoObject en tant que Datacontext et enregistre les valeurs dans ma configuration Storage. De cette façon, le rédacteur de dialogue de configuration doit simplement se lier à une valeur et celle-ci est automatiquement créée et enregistrée. (Et fourni au module pour utiliser ces paramètres bien sûr)

C’est tout simplement plus facile à utiliser qu’un dictionnaire. Mais tout le monde devrait savoir qu’en interne, il n’ya qu’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 transformer en un seul pour lister les valeurs).

var obj = new Dictionary<string, object>;
...
Console.WriteLine(obj["MyString"]);

Je pense que cela ne fonctionne que parce que tout a une ToString (), sinon vous devez connaître le type dont il s'agit et convertir l'objet en ce type.

Certains d’entre eux sont plus utiles que d’autres, j’essaie d’être minutieux.

  1. Il peut être beaucoup plus naturel d'accéder à une collection, dans ce cas ce qui est en réalité un & dictionnaire & ";, en utilisant la notation plus directe par points.

  2. Il semble que cela pourrait être utilisé comme un tuple vraiment sympa. Vous pouvez toujours appeler vos membres & Quot; Item1 & Quot ;, & Quot; Item2 & Quot; etc ... mais maintenant vous n'avez pas à le faire, c'est aussi mutable, contrairement à un tuple. Cela présente l’énorme inconvénient du manque de support intellisense.

  3. Il se peut que vous soyez mal à l'aise avec & "; les noms de membres sous forme de chaînes &"; comme c'est le cas avec le dictionnaire, vous pouvez avoir l'impression que cela ressemble trop à & "exécuter des chaînes quot ;, et cela peut conduire à coder des conventions de nommage et à travailler avec des morphèmes et des syllabes lorsque le code tente de comprendre comment utiliser les membres :-P

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

  5. Je ne pense pas que dynamic / dynamic [] fonctionne dans une boucle foreach, vous devez utiliser var, mais vous pouvez éventuellement utiliser ExpandoObject.

  6. Vous ne pouvez pas utiliser dynamic en tant que membre de données dans une classe, peut-être parce que c'est en quelque sorte un mot clé, heureusement avec ExpandoObject.

  7. Je l’attends & "est &"; Un ExpandoObject pourrait être utile pour étiqueter des éléments très génériques, avec un code différenciant en fonction des types où de nombreux éléments dynamiques sont utilisés.

Soyez sympa si vous pouviez explorer plusieurs niveaux à la fois.

var e = new ExpandoObject();
e.position.x = 5;
etc...

Ce n’est pas le meilleur exemple possible, imaginez des utilisations élégantes appropriées dans vos propres projets.

C'est dommage que vous ne puissiez pas avoir du code pour en construire quelques-uns et pour pousser les résultats à intellisense. Je ne sais pas comment cela fonctionnerait si.

Soyez gentil s'ils peuvent avoir une valeur ainsi que des membres.

var fifteen = new ExpandoObject();
fifteen = 15;
fifteen.tens = 1;
fifteen.units = 5;
fifteen.ToString() = "fifteen";
etc...

Après valueTuples, à quoi sert la classe ExpandoObject? ce code à 6 lignes avec ExpandoObject:

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

peut être écrit sur une ligne avec des tuples:

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

En plus de la syntaxe des tuples, vous avez une forte déduction de types et un support intlisense

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top