viernes, 21 de febrero de 2014

Receta No. 1-19 en C#: Creación de un Tipo Dinámico usando ExpandoObject

Tabla de Contenido

0. Introducción
1. Problema
2. Solución
3. Discusión de la Solución
4. Práctica
5. Conclusiones
6. Glosario
7. Enlaces & Literatura

0. Introducción

En la receta previa aprendimos a crear un tipo de dato anónimo a través del uso de la construcción var, sin embargo ésta sólo nos facilita la manipulación de propiedades de sólo lectura, es decir, una vez le asignemos un valor ya no podremos alterarlo en el resto del flujo del programa, tampoco agregar más propiedades. Sin embargo, como programadores contamos con una alternativa que agrega dinamismo a los tipos de datos creados en tiempo compilación: estoy hablando de la construcción dynamic en conjunción con ExpandoObject.

1. Problema

Ahora necesitamos crear tipos de datos con propiedades lectura y escritura en tiempo de ejecución (runtime).

2. Solución

El lenguaje de programación C# cuenta con dos construcciones para atacar el problema planteado: dynamic y ExpandoObject (namespace System.Dynamic).

3. Discusión de la Solución

Ya no basta con crear un tipo de dato de forma anónima con propiedades de sólo lectura. Es explícita la necesidad de crear tipos anónimos con propiedades de escritura y lectura. Esto lo alcanzamos a través del tipo dynamic y la clase ExpandoObject (namespace System.Dynamic). Veamos esto más detenidamente.

3.1 dynamic

De acuerdo con [3] el tipo dynamic permite llevar a cabo operaciones en tiempo de ejecución que pueden pasar por alto el chequeo o supervisión del compilador (la comprobación se realiza en tiempo de compilación: retrasada (delay)). dynamic, además, facilita la la interoperabilidad con APIs de COM, la manipulación del DOM [5] de HTML [6] (por supuesto, esto lo veremos más adelante).

Veamos un ejemplo de uso simple:

dynamic d;
int i = 20;
d = (dynamic)i;
Console.WriteLine(d);

Como podemos observar la sintaxis de declaración de una variable dynamic es análoga a todas las demás, en la tercera línea hacemos casting de int al tipo mencionado, y en la cuarta línea la CLR se encarga de invocar de manera implícita el método ToString sobre d.

3.2 dynamic y Object

Object [7] garantiza la detección de errores en tiempo de compilación (detección temprana), mientras que el tipo dynamic no; pues debido a su naturaleza dinámica de gestión de tipo. Véamoslo:

Archivo C# PruebaDynamicObject.cs:

Al remover el comentario sobre la línea 12, el compilador de C# genera el siguiente error:

error CS0019: Operator '+' cannot be applied to operands of type 'object' and 'int'

Al volver a añadir el comentario, la compilación y ejecución son correctas. La salida generada corresponde con el valor literal 4.

3.3 Clase System.Dynamic.DynamoObject

La clase DynamoObject (namespace System.Dynamic) fue introducida en la versión número 4 del Framework .NET. Forma parte del conjunto de artefactos que dan soporte a capacidades dinámicas al lenguaje C#. Ídem sobre el concepto que los tipos dinámicos son comprobados de forma retrasada (delay): omisión de comprobación en tiempo de compilación, pero sí por parte de la CLR: esto nos da entender que no tendremos sensación del impacto de los errores tipográficos sobre las propiedades agregadas dinámicamente, inclusive el pase de argumentos a un método, hasta que no se ejecute el programa.

A continuación un ejemplo de sintaxis simple:

dynamic expando = new ExpandoObject();
expando.Nombre = "Juan Ortiz";

Aquí creamos un instancia de ExpandoObject y enseguida creamos una propiedad string para almacenar la cadena "Juan Ortiz". De acuerdo con [1] para la creación de una instancia de ExpandoObject debemos especificar el tipo como dynamic. De lo contrario si intentamos algo como:

ExpandoObject expando = new ExpandoObject();
expando.Nombre = "Juan Ortiz";

el compilador arrojará el siguiente mensaje de error:

error CS1061: 'System.Dynamic.ExpandoObject' does not contain a definition for 'Nombre' and no extension method 'Nombre' accepting a first argument of type 'System.Dynamic.ExpandoObject' could be found (are you missing a using directive or an assembly reference?)

[Nota: En un artículo posterior me extenderé en el uso de la clase ExpandoObject.]

[Nota: Recomiendo la lectura de la discución [4].]

4. Práctica

Voy a adaptar el ejemplo en [1] para expandir y afianzar el conocimiento del uso de la clase ExpandoObject para crear tipos de datos anónimos y dinámicos con propiedades de lectura y escritura. OK, veamos:


En la línea 14 creamos una instancia de ExpandoObject y la asignamos a un objeto de tipo dynamic (requerimiento). Desde la línea 15 a 21 se crean propiedades las siguientes propiedades:

  • Nombre
  • Apellido
  • Edad, y
  • Familia

Familia es una propiedad de tipo ExpandoObject, esto nos da la oportunidad de agregar más propiedades a la misma. Por ejemplo:

  • Papa
  • Mama, y 
  • Hermano

Las líneas 24-29 muestran los valores de cada una de estas propiedades.

Ahora, en la línea 32 se modifica el valor de la propiedad Edad por 44. Gracias a esta propiedad de escritura, en la línea 35 se crea una nueva propiedad -Hermana- y se asocia con la propiedad Familia.

Compilamos:
  1. csc /target:exe /out:ExpandoEjemplo.exe ExpandoEjemplo.cs
Enseguida ejecutamos:
  1. ExpandoObject.exe
Captura de pantalla de ejecución:
Ejecución ExpandoEjemplo
Figura 1. Ejecución ExpandoEjemplo.exe.

5. Conclusiones

Apredimos a usar el tipo dynamic junto con la clase System.Dynamic.ExpandoObject; útiles para la creación de tipos de datos en tiempo de ejecución junto con propiedades de lectura y escritura. También vimos la diferencia entre object y dynamic: el primero realiza comprobación de tipo en tiempo de compilación, el segundo, en tiempo de ejecución. Al final creamos un ejemplo útil donde comprobamos la funcionalidad de la clase ExpandoObject.

6. Glosario

- API
- CLR
- Dinámico
- DOM
- HTML
- Runtime
- Tiempo de ejecución

7. Enlaces & Literatura

[1]: Visual C# 2010 Recipes by Allen Jones and Adam Freeman. Copyright 2010 Allen Jones and Adam Freeman, 978-1-4302-2525-6.
[4]: c# - What are the true benefits of ExpandoObject? - Stack Overflow - http://stackoverflow.com/questions/1653046/what-are-the-true-benefits-of-expandoobject
[5]: Document Object Model, the free encyclopedia - https://en.wikipedia.org/wiki/Document_Object_Model
[6]: HTML, the free encyclopedia - https://en.wikipedia.org/wiki/HTML


J

No hay comentarios:

Publicar un comentario

Envíe sus comentarios, dudas, sugerencias, críticas. Gracias.