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: Dynamic 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);
En segundo lugar, 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;
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);
}
}
Además, tenga en cuenta que nada le impide aceptar argumentos de eventos de forma dinámica. En otras palabras, en lugar de usar EventHandler
, puede usar lo EventHandler<dynamic>
que haría que el segundo argumento del controlador sea dynamic
.
d.MyEvent = null;
, o no?var expando = new { Address = new { State = "WA" } }; Console.WriteLine(expando.Address.State);
encuentro esto más legible pero ymmv. Y dado que está estáticamente escrito, es más útil en este contexto.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.
fuente
List<dynamic>
yIEnumerable<dynamic>
usar WPF4El beneficio real para mí es el enlace de datos totalmente sin esfuerzo de XAML:
...
...
fuente
La interoperabilidad con otros idiomas fundados en el
DLR
es la razón # 1 en la que puedo pensar. No puedes pasarlosDictionary<string, object>
como no es unIDynamicMetaObjectProvider
. Otro beneficio adicional es que implementa loINotifyPropertyChanged
que significa que en el mundo de enlace de datos de WPF también tiene beneficios adicionales más allá de lo queDictionary<K,V>
puede proporcionarle.fuente
Se trata de la conveniencia del programador. Me imagino escribiendo programas rápidos y sucios con este objeto.
fuente
Creo que tendrá un beneficio sintáctico, ya que ya no estarás "falsificando" propiedades agregadas dinámicamente usando un diccionario.
Eso, e interoperar con lenguajes dinámicos, creo.
fuente
Es un ejemplo de un 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 :
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 de lenguajes dinámicos como JavaScript o PHP.
fuente
Hay algunos casos donde 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 hace las cosas más fáciles.
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).fuente
Creo que eso solo funciona porque todo tiene un ToString (), de lo contrario, tendría 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.
Puede ser mucho más natural acceder a una colección, en este caso lo que efectivamente es un "diccionario", utilizando la notación de puntos más directa.
Parece que esto podría usarse como una Tupla realmente agradable. Todavía puede llamar a sus miembros "Elemento1", "Elemento2", 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.
Puede sentirse incómodo con los "nombres de miembros como cadenas", como se siente con el diccionario, puede sentir que es muy parecido a "ejecutar cadenas", y puede llevar a codificar convenciones de nombres y trabajar con morfemas y las sílabas cuando el código está intentando entender cómo usar los miembros :-P
¿Se puede asignar un valor a un ExpandoObject en sí o solo a sus miembros? Compare y contraste con dinámico / dinámico [], use el que mejor se adapte a sus necesidades.
No creo que dynamic / dynamic [] funcione en un bucle foreach, debe usar var, pero posiblemente puede usar ExpandoObject.
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.
Supongo que "es" un Objeto de Expando, podría ser útil para etiquetar cosas muy genéricas, con un código que se diferencia en función de los tipos en los que se utilizan muchas cosas dinámicas.
Sé amable si pudieras profundizar en varios niveles a la vez.
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 un valor tan bien como los miembros.
fuente
Después de valueTuples, ¿de qué sirve la clase ExpandoObject? este código de 6 líneas con ExpandoObject:
se puede escribir en una línea con tuplas:
Además con la sintaxis de tupla, tiene una fuerte inferencia de tipos y soporte intlisense
fuente