web-dev-qa-db-fra.com

Quels sont les avantages réels de ExpandoObject?

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

Y a-t-il des avantages à utiliser un Dictionary<string, object> , ou même un Hashtable ? 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 mieux, ou substantiellement différent, que:

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

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

Quels sont les avantages réels en utilisant ExpandoObject au lieu d'utiliser simplement un type de dictionnaire arbitraire, outre le fait de ne pas être évident que vous utilisez un type qui sera utilisé être déterminé au moment de l'exécution.

563
Reed Copsey

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 de ExpandoObject: Dynamique en C # 4.0: Présentation de ExpandoObject .

Rapidement, ExpandoObject peut vous aider à créer des objets hiérarchiques complexes. Par exemple, imaginons que vous ayez 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;

       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);
   }
}
665
Alexandra Rusina

Un avantage est pour 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. Par conséquent, 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.

74
itowlson

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}" />
42
bjull

L'interopérabilité avec d'autres langages fondés 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 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 par rapport à ce que Dictionary<K,V> peut vous fournir.

27
Drew Marsh

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

19
ChaosPandion

Je pense que cela aura un avantage syntaxique, puisque vous ne serez plus en train de "simuler" des propriétés ajoutées de façon dynamique en utilisant un dictionnaire.

Cela, et interopérons avec des langages dynamiques, je pense.

14
gn22

C’est un exemple tiré d’excellent article de MSDN sur l’utilisation de ExpandoObject pour la création de 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 de 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 une certaine 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 la classe DynamicObject , nous pouvons introduire des éléments de programmation fonctionnelle dans notre code C #, que nous connaissons dans les langages dynamiques comme JavaScript ou PHP.

11
sgnsajgon

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 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 ça rend les choses plus faciles parfois.

Donc, pour répondre directement à votre question: il est plus facile d’écrire et de lire. Mais techniquement, il s’agit essentiellement d’un Dictionary<string,object> (vous pouvez même le convertir en un seul pour lister les valeurs).

4
n1LWeb