Pregunta

El Objeto Expando La clase que se agrega a .NET 4 le permite establecer propiedades arbitrariamente en un objeto en tiempo de ejecución.

¿Hay alguna ventaja en esto sobre el uso de un Dictionary<string, object>, o realmente incluso un Tabla de picadillo?Hasta donde puedo decir, esto no es más que una tabla hash a la que puedes acceder con una sintaxis un poco más concisa.

Por ejemplo, ¿por qué es esto?

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

Realmente mejor, o sustancialmente diferente, que:

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

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

Qué real Se obtienen ventajas al usar ExpandoObject en lugar de simplemente usar un tipo de diccionario arbitrario, además de no ser obvio que estás usando un tipo que se determinará en tiempo de ejecución.

¿Fue útil?

Solución

Desde que escribí el artículo de MSDN al que te refieres, creo que tengo que responder a este.

Primero, anticipé esta pregunta y es por eso que escribí una publicación de blog que muestra un caso de uso más o menos real para ExpandoObject: Dinámico en C # 4.0: Presentación del ExpandoObject .

En breve, ExpandoObject puede ayudarlo a crear objetos jerárquicos complejos. Por ejemplo, imagine que tiene un diccionario dentro de un diccionario:

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

Cuanto más profunda es la jerarquía, más feo es el código. Con ExpandoObject se mantiene elegante y legible.

dynamic expando = new ExpandoObject();
expando.Address = new ExpandoObject();
expando.Address.State = "WA";
Console.WriteLine(expando.Address.State);

Segundo, como ya se señaló, ExpandoObject implementa la interfaz INotifyPropertyChanged que le brinda más control sobre las propiedades que un diccionario.

Finalmente, puede agregar eventos a ExpandoObject como aquí:

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

Otros consejos

Una ventaja es para los escenarios vinculantes. Las cuadrículas de datos y las cuadrículas de propiedades recogerán las propiedades dinámicas a través del sistema TypeDescriptor. Además, el enlace de datos WPF comprenderá las propiedades dinámicas, por lo que los controles WPF pueden vincularse a un Objeto de Expando más fácilmente que un diccionario.

La interoperabilidad con lenguajes dinámicos, que esperarán propiedades DLR en lugar de entradas de diccionario, también puede ser una consideración en algunos escenarios.

El beneficio real para mí es el enlace de datos totalmente sin esfuerzo de XAML:

public dynamic SomeData { get; set; }

...

SomeData.WhatEver = "Yo Man!";

...

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

Interoperabilidad con otros lenguajes basados ​​en el DLR es la razón número uno que se me ocurre.No puedes pasarles un Dictionary<string, object> como no es un IDynamicMetaObjectProvider.Otro beneficio adicional es que implementa INotifyPropertyChanged lo que significa que en el mundo del enlace de datos de WPF también tiene beneficios adicionales más allá de lo que Dictionary<K,V> puede proporcionarte.

Se trata de la conveniencia del programador. Me imagino escribiendo programas rápidos y sucios con este objeto.

Creo que tendrá un beneficio sintáctico, ya que ya no serás " fingiendo " propiedades agregadas dinámicamente mediante el uso de un diccionario.

Eso, e interoperabilidad con lenguajes dinámicos, creo.

Es un ejemplo del excelente artículo de MSDN sobre el uso de ExpandoObject para crear tipos dinámicos ad-hoc para datos estructurados entrantes (es decir, XML, Json).

También podemos asignar delegado a la propiedad dinámica 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);

Por lo tanto, nos permite inyectar algo de lógica en un objeto dinámico en tiempo de ejecución. Por lo tanto, junto con expresiones lambda, cierres, palabras clave dinámicas y clase DynamicObject , podemos introducir algunos elementos de programación funcional en nuestro código C #, que conocemos por lenguajes dinámicos como JavaScript o PHP.

Hay algunos casos en que esto es útil. Lo usaré para un shell modularizado, por ejemplo. Cada módulo define su propio cuadro de diálogo de configuración enlazado a sus configuraciones. Le proporciono un ExpandoObject como Datacontext y guardo los valores en mi configuración de Almacenamiento. De esta forma, el escritor del Diálogo de configuración solo tiene que vincularse a un valor y se crea y guarda automáticamente. (Y proporcionado al módulo para usar estas configuraciones, por supuesto)

Es 'simplemente más fácil de usar que un diccionario. Pero todos deben tener en cuenta que internamente es solo un Diccionario.

Es como LINQ solo azúcar sintáctico, pero a veces facilita las cosas.

Entonces, para responder su pregunta directamente: es más fácil de escribir y más fácil de leer. Pero técnicamente es esencialmente un Dictionary<string,object> (Incluso puede convertirlo en uno para enumerar los valores).

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

Creo que eso solo funciona porque todo tiene un ToString (), de lo contrario tendrías que saber el tipo que era y emitir el 'objeto' a ese tipo.


Algunos de estos son útiles más a menudo que otros, estoy tratando de ser minucioso.

  1. Puede ser mucho más natural acceder a una colección, en este caso lo que efectivamente es un " dictionary " ;, utilizando la notación de punto más directa.

  2. Parece como si esto pudiera ser usado como una Tupla realmente agradable. Todavía puede llamar a sus miembros & Quot; Item1 & Quot ;, & Quot; Item2 & Quot; etc ... pero ahora no tiene que hacerlo, también es mutable, a diferencia de una Tupla. Esto tiene el gran inconveniente de la falta de soporte inteligente.

  3. Es posible que se sienta incómodo con " nombres de miembros como cadenas " ;, como se siente con el diccionario, puede sentir que es muy parecido a " ejecutar cadenas quot ;, y puede llevar a codificar convenciones de nomenclatura y trabajar con morfemas y sílabas cuando el código intenta comprender cómo usar los miembros :-P

  4. ¿Puede asignar un valor a un ExpandoObject en sí mismo o solo a sus miembros? Compare y contraste con dinámico / dinámico [], use el que mejor se adapte a sus necesidades.

  5. No creo que dinámico / dinámico [] funcione en un bucle foreach, debe usar var, pero posiblemente puede usar ExpandoObject.

  6. No puede usar Dynamic como miembro de datos en una clase, tal vez porque es al menos algo así como una palabra clave, con suerte puede hacerlo con ExpandoObject.

  7. Lo espero " es " un objeto ExpandoObject podría ser útil para etiquetar cosas muy genéricas, con un código que diferencie según los tipos en los que se utilizan muchas cosas dinámicas.


Sé amable si pudieras profundizar en varios niveles a la vez.

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

Ese no es el mejor ejemplo posible, imagine usos elegantes según corresponda en sus propios proyectos.

Es una pena que no pueda hacer que el código construya algunos de estos y empuje los resultados a intellisense. Sin embargo, no estoy seguro de cómo funcionaría esto.

Sé amable si pudieran tener tanto valor como miembros.

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

Después de valueTuples, ¿de qué sirve la clase ExpandoObject? este código de 6 líneas con ExpandoObject:

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

se puede escribir en una línea con tuplas:

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

además de la sintaxis de tupla, tienes una fuerte inferencia de tipos y soporte intlisense

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top