Mostrando entradas con la etiqueta Capítulo02. Mostrar todas las entradas
Mostrando entradas con la etiqueta Capítulo02. Mostrar todas las entradas

jueves, 9 de julio de 2015

Receta Multithreading en C# No. 2-5: Envío de Mensajes entre Threads con ManualResetEventSlim

Índice

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

0. Introducción

En la receta multithreading anterior (2-4) usamos la clase AutoResetEvent para el envío de mensajes o notificaciones entre threads. Esta operación nos permitió activar o desactivar la continuación de la ejecución de las tareas de un proceso asociado a un thread a través del uso de los miembros disponibles en esa misma clase: Set, y WaitOne. Ahora estudiáremos cómo usar la clase ManualResetEventSlim para enviar mensajes múltiples threads.

1. Problema

Requerimos un método para el envío de mensajes o notificaciones a múltiples threads.

2. Solución

Con la clase ManualResetEventSlim podemos enviar una notificación a un proceso para que múltiples threads continúen ejecutando las tareas (instrucciones) definidas en tal proceso.

3. Discusión de la Solución

La clase ManualResetEventSlim [2] provee una versión reducida de ManualResetEvent [4]. Esta última la hemos tratado con detalle en Receta C# No. 4-8: Sincronizar la Ejecución de Múltiples Threads usando un Evento (lectura que sugiero para facilitar la comprensión de ManualResetSlim).

A diferencia de AutoManualReset, ManualResetSlim funciona análogamente como una puerta por donde pueden transitir múltiples threads. En la Figura 1 se muestra el análogo entre estos dos enfoques de control y de envío de mensajes/notificaciones en la ejecución de múltiples threads.
AutoResetEvent vs. ManualResetEvent
Figura 1. AutoResetEvent vs. ManualResetEvent [6].
A la derecha vemos la analogía de un torniquete con la clase AutoResetEvent: un único thread puede pasar por el torniquete (continuar su ejecución); mientras, que la clase ManualResetEvent es similar a una puerta amplia (izquierda): múltiples threads pueden pasar al mismo tiempo. La clase ManualResetEventSlim opera similar a esta última pero de forma más flexible. Esta flexibilidad y optimización es para tiempos de espera más cortos para los threads.

4. Práctica: Código C#

En este ejemplo controlaremos la ejecución de 3 threads que tendrán asociado un proceso. Desde el thread Main enviaremos las señales de suspensión y continuación de la ejecución de los threads según sea necesario.


En la línea 12 creamos un objeto ManualResetEventSlim para el control de señales de suspensión y continuación de la ejecución de threads. Notar que la instanciación de este objeto empieza sin ser notificado: argumento false. En las líneas 19-21 creamos tres objetos Thread a los cuales asignamos la ejecución del método Proceso.

Una vez creados los tres threads anteriores, pasamos a iniciar su ejecución: líneas 24-26. En la salida estándar se mostrará el mensaje de inicio de cada thread. Cada thread iniciará un tiempo de espera acorde al valor del argumento tiempoEspera: línea 61.

Ahora, desde la línea 32, en Main, envíamos la señal de continúación: evento.Set(). Pasados dos segundos, Thread.Sleep(FromSeconds(2)) (precisamente en la línea 34), bloqueamos la ejecución hasta que se invoque nuevamente el método Set(). Los threads que ya han superado el tiempo de espera en la línea 61 terminarán su ejecución, los restantes seguirán esperando hasta que se vuelva a enviar una nueva señal de continuación: línea 42.

En la Animación 1 se puede apreciar mejor el efecto que tiene la invocación de los métodos:
  • Reset, 
  • Set, y 
  • Wait.
Compilación:


  1. csc /target:exe NotificacionMultiplesThreads.cs


Ejecución assembly:


  1. .\NotificacionMultiplesThreads.exe

> Prueba de ejecución (local):
Ejecución assembly NotificacionMultiplesThreads.exe
Animación 1. Ejecución assembly NotificacionMultiplesThreads.exe.

5. Conclusiones

Estudiamos la clase ManualResetEventSlim y reconocimos que nos es útil para controlar el flujo de ejecución de múltiples threads. Los métodos Reset, Set, y Wait son los miembros que permiten:
  • bloquear un conjunto de threads, 
  • desbloquear un conjunto de threads, y 
  • bloquear un thread en particular durante un período indeterminado de tiempo.
respectivamente.

Entendimos a la clase ManualResetEventSlim, como una puerta amplia por donde pueden pasar (ejecutarse) múltiples threads.

La próxima receta multithreading la dedicaremos a estudiar la clase CountDownEvent que como veremos es útil para esperar hasta que cierto número de operaciones se hayan ejecutado.

6. Glosario

  • Evento
  • Método
  • Señal
  • Thread

7. Literatura & Enlaces

[1]: Multithreading in C# 5.0 Cookbook by Eugene Agafonov. Copyright 2013 Eugene Agafonov, 978-1-84969-764-4.
[2]: ManualResetEventSlim Class (System.Threading) -
https://msdn.microsoft.com/en-us/library/system.threading.manualreseteventslim(v=vs.110).aspx
[3]: Threading in C# - Part 2 - Basic Synchronization -
http://www.albahari.com/threading/part2.aspx#_ManualResetEvent
[4]: ManualResetEvent Class (System.Threading) -
https://msdn.microsoft.com/en-us/library/system.threading.manualresetevent(v=vs.110).aspx
[5]: Receta C# No. 4-8: Sincronizar la Ejecución de Múltiples Threads usando un Evento - http://ortizol.blogspot.com/2014/07/receta-c-no-4-8-sincronizar-la-ejecucion-de-multiples-threads-usando-un-evento.html
[6]: Multithreading in .Net and C#: EventWaitHandler: AutoResetEvent and ManualResetEvent - http://multithreads.blogspot.com/2007/09/eventwaithandler-autoresetevent-and.html


J

viernes, 3 de julio de 2015

Receta T-SQL No. 2.4: Escritura de una Expresión CASE Simple

Índice

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

0. Introducción

En esta oportunidad, aprenderemos una receta sencilla para composición de expresiones CASE simples. Ya veremos que esta construcción de T-SQL nos será útil para la evaluación del valor de una columna o variable que abarque un conjunto definido de posibles valores.

1. Problema

Requerimos evaluar diferentes valores de una variable o columna para determinar el valor de salida para cada valor de entrada. Adicionalmente, se requiere que la evaluación se efectúe sobre el contenido de una columna de una tabla o de una variable.

2. Solución

La solución a este requerimiento es recurrir a la construcción de T-SQL CASE [2]. Esta construcción evalua una lista de condiciones y puede retornar una de múltiples expresiones especificadas en su cuerpo de declaración. (Vale anotar que esta expresión es análoga a la construcción de control de flujo switch del lenguaje de programación C#.)

Los formatos posibles de CASE son:
  • La versión simple consiste en especificar un valor del conjunto de valores posibles de la variable o columna.
  • La versión alternativa consiste en formar una expresión booleana o de búsqueda. (Esta versión la estudiáremos con el detalle que corresonda en la siguiente receta.)

3. Discusión de la Solución

In extenso, la construcción CASE posee estas dos formas declarativas para su uso de evaluación de valores y expresiones booleanas:

3.1 Versión simple

CASE variable_o_columna
    WHEN valor_1 THEN expresion_resultado
    WHEN valor_2 THEN expresion_resultado
    WHEN valor_3 THEN expresion_resultado
    WHEN valor_n THEN expresion_resultado
   [ELSE expresion_resultado_alternativo]
END

Notemos que la expresión ELSE es alternativa en este caso.

3.2 Versión con expresión booleana

CASE
    WHEN expresion_booleana_1 THEN expresion_resultado
    WHEN expresion_booleana_2 THEN expresion_resultado
    WHEN expresion_booleana_3 THEN expresion_resultado
    WHEN expresion_booleana_n THEN expresion_resultado
   [ELSE expresion_resultado_alternativo]
END

La expresión booleana, recordemos, puede incluir cualquier de los operadores de comparación disponibles [4].

4. Práctica: Código T-SQL

En este primer ejemplo usaremos la columna GroupName de la tabla HumanResources.Department de la base de datos de ejemplo AdventureWorks. Con el uso de CASE formaremos una nueva columna la cual contendrá un valor de representación a la versión extendida del campo GraoupName. Los nombres de los campos nuevos que usaremos son:
  • Módulo A, 
  • Módulo B, 
  • Módulo C, y 
  • Módulo D
Notemos que esta versión simple de CASE, tenemos hasta cuatro expresiones simples que serán contrastadas con el valor de la columna GroupName. El valor que aparece frente a THEN será el que se asigne a la columna Modulo.


Una vez ejecutemos esta expresión T-SQL, obtendremos el siguiente resultado en Microsoft SQL Management Studio 2014:
Escritura de una Expresión CASE Simple - Resultado ejemplo 1
Figura 1. Escritura de una Expresión CASE Simple - Resultado ejemplo 1.

5. Conclusiones

Hemos abordado la conformación de expresiones CASE simples con la descripción sintáctica y un ejemplo de uso. Es importante resaltar que esta construcción nos simplifica la evaluación de valores de variables o columnas de forma ordenada, como fue el caso del ejemplo en donde seleccionamos como entrada una cadena de caracteres y de acuerdo a su valor asignamos una salida a una columna virtual. En la próxima receta T-SQL, estudiáremos con más detalle la versión con expresión booleana o de búsqueda (como la llaman en [1]).

6. Glosario

  • Consulta
  • Microsoft SQL Management Studio
  • SQL Server
  • T-SQL

7. Literatura & Enlaces

[1]: SQL Server 2012 T-SQL Recipes - A Problem-Solucion Approach by Jason Brimhall, David Dye, Jonathan Gennick, Andy Roberts, and Wayne Sheffield. Copyright 2012 Jason Brimhall, David Dye, Jonathan Gennick, Andy Roberts, and Wayne Sheffield, 978-1-4302-4200-0.
[2]: CASE (Transact-SQL) - https://msdn.microsoft.com/en-us/library/ms181765.aspx?f=255&MSPPError=-2147217396
[3]: Sentencias en C# - Parte 2 - http://ortizol.blogspot.com/2013/10/sentencias-en-c-parte-2.html
[4]: Comparison Operators (Transact-SQL) - https://msdn.microsoft.com/en-us/library/ms188074.aspx


J

jueves, 9 de abril de 2015

Receta Multithreading en C# No. 2-3: Limitar el Acceso a un Recurso Compartido con SemaphoreSlim

Índice

0. Introducción
1. Problema
2. Solución
3. Discusión de la Solución
3.1 Propiedades de `SemaphoreSlim`
3.2 Constructores de `SemaphoreSlim`
4. Práctica: Código C#
5. Conclusiones
6. Glosario
7. Literatura & Enlaces

0. Introducción

En esta nueva receta multithreading en C# aprenderemos cómo limitar el acceso a un recurso compartido con la clase SemaphoreSlim. Ya veremos que esto nos puede resultar útil para ciertas restricciones que puedieran ser impuestas sobre un recurso compartido: archivo, base de datos, recurso de red, etc. El ejemplo nos ilustrará cómo podemos utilizar ese artefacto para simular el acceso concurrente a una base de datos. (Evidentemente este tipo de ejemplos será únicamente para ilustrar el concepto base de esta clase y su funcionalidad.)

1. Problema

Requerimos de una técnica programática en C# para limitar el número de threads que pueden acceder concurrentemente a un recurso de acceso compartido.

2. Solución

La biliblioteca base de clases (BCL) de .NET cuenta con la clase `SemaphoreSlim` para responder a el requerimiento previo.

3. Discusión de la Solución

La clase `SemaphoreSlim` reside en el espacio de nombres System.Threading. Esta clase básicamente constituye [1] una versión alternativa (lightweight) a la clase `Semaphore` [4, 3] que para el propósito solicitado permite limitar el número de threads (o directus et simplux, hilos) que tienen permitido acceder a un recurso compartido de forma concurrente [2].

3.1 Propiedades sobresalientes de `SemaphoreSlim`


La clase `Semaphore` cuenta con las propiedades `AvailableWaitHandle`, y `CurrentCount`:
Propiedades de SemaphoreSlim
Figura 1. Propiedades de SemaphoreSlim [2].
Como se describe en la Figura 1, la propiedad `AvailableWaitHandle` retorna el objeto `WaitHandle` que es requerido para realizar esperas sobre el semáforo. Mientras que la propiedad `CurrentCount` retorna el número de threads permitidos sobre el recurso compartido. Esta última propiedad se establece al instanciar una clase de `Semaphore`, dado que se requiere especificar la cantidad límite de threads que podrán acceder de forma concurrente al recurso compartido en cuestión.

3.2 Constructores de `SemaphoreSlim`


Descripción general de los constructores disponibles en `SemaphoreSlim` [2]:
Constructores de SemaphoreSlim
Figura 2. Constructores de `SemaphoreSlim` [2].

3.2 Notas importantes de uso de `SemaphoreSlim`

Desde [1] nos advierten:
«There is no sense in using it -`SemaphoreSlim`-, except in one very important scenario, we can create a named semaphore like a named mutes and use it to synchronize threads in different programs. Semaphore does not use Windows Kernel semaphores and does not support interprocess synchronization, so use Semaphore in this case.

4. Práctica: Código C#

Pasemos a crear un ejemplo sencillo pero funcionalmente ilustrativo de uso de la clase `SemaphoreSlim` en el que vamos a simular el acceso a una base de datos (recurso compartido) por múltiples threads:

En las líneas 35-49 se declara el método `AccederBaseDatos`; este método lleva a cabo las siguientes operaciones:

  1. Linea 37: Muestra mensaje en la salida estándar (consola) anunciando el intento de acceso a la base de datos por parte del thread actual.
  2. Línea 38: Bloquea el thread actual hasta que tenga permiso de acceder a la base de datos.
  3. Línea 40: Anuncia el acceso recién permitido a la base de datos al thread.
  4. Línea 43: Simula tiempo de una operación transaccional o de consulta a la base de datos.
  5. Línea 45: Anuncia que el thread ha finalizado su ejecución.
  6. Línea 48: Libera el thread desde pool de threads.
Por otro parte, el método de inicio de ejecución de la aplicación, `Main` (líneas 12-31), se encarga de instanciar hasta 6 threads y ponerlos en ejecución sobre el método `AccederBaseDatos` (línea 24). Cada thread recibe un nombre y un tiempo de espera (tiempo simulado de ejecución de la operación transaccional o de consulta): líneas 20 y 22, respectivamente.

Compilación:


  1. csc /t:exe AccesoBaseDatosConSemaphoreSlim.cs


Ejecución assembly:


  1. .\AccesoBaseDatosConSemaphoreSlim.exe



> Prueba de ejecución (local):
Ejecución assembly AccesoBaseDatosConSemaphoreSlim.exe
Figura 3. Ejecución assembly AccesoBaseDatosConSemaphoreSlim.exe.

5. Conclusiones

En esta receta multithreading hemos aprendido a entender y a usar la clase `SemaphoreSlim` del namespace System.Threading para controlar el límite de threads que pueden acceder de forma concurrente a un recurso compartido. En el ejemplo de la sección 4 se simuló el acceso concurrente a una base de datos por parte de 6 threads: sólo pueden acceder de manera simultánea 4 threads, los 2 restantes deberán esperar a que uno o más threads finalicen las operaciones transaccionales o de consulta especificadas y la liberación correspondiente. En la próxima receta multithreading aprederemos a usar la clase `AutoResetEvent` para el envío de notificaciones entre threads.

6. Glosario

  • .NET
  • BCL
  • Hilo
  • Multithreading
  • Recurso compartido
  • Thread

7. Literatura & Enlaces

[1]: Multithreading in C# 5.0 Cookbook by Eugene Agafonov. Copyright 2013 Eugene Agafonov, 978-1-84969-764-4.
[2]: SemaphoreSlim Class (System.Threading) - https://msdn.microsoft.com/en-us/library/vstudio/system.threading.semaphoreslim(v=vs.100).aspx
[3]: Semaphore Class (System.Threading) - https://msdn.microsoft.com/en-us/library/vstudio/system.threading.semaphore(v=vs.100).aspx
[4]: OrtizOL - Experiencias Construcción Software (xCSw): Receta C# No. 4-10: Sincronización de Múltiples Threads usando un Semáforo - http://ortizol.blogspot.com/2014/07/receta-csharp-no-4-10-sincronizacion-de-multiples-threads-usando-un-semaforo.html

J

lunes, 19 de mayo de 2014

Receta No. 2-16 en C#: Manipulación de Valores Enteros Grandes

Tabla de Contenido

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

0. Introducción

En esta receta vamos a aprender acerca de la manipulación de valores enteros grandes. Esto representa una oportunidad para obtener conocimiento y técnica, útil para aquellas aplicaciones científicas o financieras (por poner un ejemplo) que deben realizar cómputos sobre valores que van más allá del soporte común en aplicaciones rutinarias. Esto nos obliga a echar un vistazo a varios de los artefactos del Framework .NET que posibilitan este tipo tareas. ¡Veamos!

1. Problema

Una entidad bancaria llamada Bancamiga ha solicitado a nuestra compañía de construcción de software -Ad Infinitum Systems-, la construcción de un módulo de cómputo que requiere la manipulación de cuentas con un largo historial de registros que incluyen valores de operaciones por encima de los soportados actualmente por el módulo legado.

2. Solución

El arquitecto de software apenas recibió el requerimiento del módulo a desarrollo, comprendió enseguida que uno de los artefactos fundamentales que provee el Framework .NET es la estructura System.Numerics.BigInteger. Esta estructura supera los límites de los tipos de datos por valor integrados (e.g., Int32 [2], Int64 [3]; -2^31 hasta 2^31-1, y, -2^63 hasta 2^32-1, respectivamente).

3. Discusión de la Solución

En artículos previos tuvimos -Tipos Numéricos en C#- la oportunidad de conocer acerca de los tipos numéricos en C#:
Tipos numéricos predefinidos en C#.
Figura 1. Tipos numéricos predefinidos en C# [5].
El entero de mayor capacidad que vemos en la Figura 1 es long. Rango:
  • Límite inferior: -2^63 = -9223372036854775808
  • Límite superior: 2^63-1 = 9223372036854775807
Nuestros cálculos diarios no sobrepasan estos valores enteros. Sin embargo, en muchas organizaciones esto sí que representa un límite de capacidad de almacenamiento de valores numéricos.

En vista de lo anterior, el Framework .NET posee la estructura System.Numerics.BigInteger [6]. Esta estructura supera estos límites permitiendo la manipulación en memoria de valores enteros arbitrarios (según los requerimientos de cómputo, por ejemplo).

Constructores disponibles de BigInteger con los que podemos crear un valor entero a partir, por ejemplo, de un arreglo de bytes, los enteros estándar:
Constructores de la estructura BigInteger
Figura 2. Constructores de la estructura BigInteger [6].
[Nota: Recomiendo ver el listado completo de los métodos de BigInteger que permiten al programador realizar comparaciones, igualdades, desplazamiento de bits a la izquierda y a la derecha, negación unaria, aritmética básica, entre muchas más.]

A continuación un par de ejemplos de uso de esta estructura:

3.1 Instanciación

BigInteger bigIntDesdeDouble = new BigIntger(311572.1415796);
BigInteger bigIntDesdeInt64 = new BigInteger(9223372036854775707);

Console.WriteLine(bigIntDesdeDouble); // Salida: 311572.1415796
Console.WriteLine(bigIntDesdeInt64); // Salida: 9223372036854775707

3.2 Creación a partir de arreglo de bytes

byte[] arregloBytes = {10, 9, 8, 7,6, 5, 4, 3, 2, 1, 0};

BigInteger bi = new BigInteger(arregloBytes);
Console.WriteLine("El valor de `bi` es {0}.", bi);

3.3 Creacion a partir de cadenas de caracteres


Prueba de compilación, ejecución, y salida:
Creación de instancias de BigInteger a partir de objetos string
Figura 3. Creación de instancias de BigInteger a partir de objetos string.

4. Práctica: Código Fuente C#

Varios programadores han empezado a crear ejemplos. Uno de ellos ha realizado el siguiente código fuente C# para demostrar el uso de BigInteger:


Compilación:


  1. csc /target:exe /reference:System.Numerics.dll DemoBigInteger.cs

Resultado:
Instanciación de la clase BigInteger.
Figura 4. Instanciación de la clase BigInteger.

Conclusiones

Interesante receta en donde hemos aprendido a crear valor enteros grandes. La clase BigInteger (namespace System.Numerics) es la solución que provee el Framework .NET para sortear la manipulación de cadenas de valores numéricos extensas. Esto nos puede resultar útil, por ejemplo, para aplicaciones financieras, o científicas.

Glosario

  • BigInteger
  • Entero
  • Instanciación
  • Límite
  • Valor

Literatura & Enlaces

[1]: Visual C# 2010 Recipes by Allen Jones and Adam Freeman. Copyright 2010 Allen Jones and Adam Freeman, 978-1-4302-2525-6.
[2]: Int32 (Estructura) (System) - http://msdn.microsoft.com/es-es/library/system.int32(v=vs.110).aspx
[3]: Int64 (Estructura) (System) - http://msdn.microsoft.com/es-es/library/system.int64(v=vs.110).aspx
[4]: Tipos Numéricos en C# - http://ortizol.blogspot.com/2013/07/tipos-numericos-en-c-parte-1.html
[5]: C# 5.0 in a Nutshell by Joseph Albahari and Ben Albahari. Copyright 2012 Joseph Albahari and Ben Albahari, 978-1-449-32010-2.
[6]: BigInteger (Structure) (System.Numerics) - http://msdn.microsoft.com/es-es/library/system.numerics.biginteger(v=vs.110).aspx


M

sábado, 10 de mayo de 2014

Receta No. 2-14 en C#: Serializar el Estado de un Objeto usando JSON

Tabla de Contenido

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

0. Introducción

En la receta anterior -Persistencia de Datos de Objeto en un Archivo-, aprendimos y pusimos en práctica los conceptos esenciales de serialización: usamos las clases BinaryFormatter y SoapFormatter para serializar/deserializar los datos de trabajo (o estado) de objetos almacenados en las colecciones Hashtable, ArrayList.  En esta nueva ocasión, vamos a utilizar un proceso de serialización alternativo independiente del lenguaje: JSON.

1. Problema

La compañía ABC ha decidido hacer una alianza comercial con la organización XYZ, en busca de nuevas oportunidades en el mercado emergente del desarrollo de soluciones industriales para el sector de la construcción. Estas dos organización cuentan con dos sistemas informáticos de tecnología heterogéneas. Este problema ya fue reportado al arquitecto empresarial para que coordine un proyecto que permita y facilite a los sistemas intercambiar información.

2. Solución

Inmediatamente el arquitecto de software recibió el requisito, planteó varias alternativas para el intercambio de información: parsing de archivos de texto plano generados entre los dos sistemas, luego serán cargados con una utilidad de ETL [4] desarrollada a la medida; alternativamente se planteó otro medio más transparente, inclusive, no crea dependencias respecto a una plataforma en la notación de los datos. El conceptó resonó entre todos los integrantes del equipo de integración: JSON (JavaScript Object Notation).

En esencia, para lograr serializar objetos vía JSON necesitamos de las siguientes acciones programáticas:
  1. Crear un objeto Stream para especificar la ruta de destino y origen: serializar, y deserializar, respectivamente.
  2. Crear una instancia de DataContractJsonSerializer. Al constructor de este tipo se le debe especificar el tipo de dato a serializar/deserializar
    1. El método WriteObject permite serializar el estado de un objeto.
    2. El método ReadObject permite deserializar el estado de un objeto.

3. Discusión de la Solución

Hemos mencionado que la clase DataContractJsonSerializer [6] posee toda la maquinaria para serializar y desarializar el estado de un objeto utilizando la notación JSON. Antes de continuar, explicaré grosso modo la tecnología de notación JSON.

3.1 ¿Qué es JSON?

De acuerdo con [2, 3], JSON es un formato (o estándar) de intercambio de datos liviano. Facilita la lectura/escritura de la representación y de los datos para humanos. En cuanto a las máquinas, se facilita el proceso de parsing [5] y generación de datos estructurados de forma rápida y eficiente.

Estructuras de construcción sobre las que se basa JSON:
  • Colección de pares llave (nombre) / valor. (Se puede analogar esta estructura con las colecciones de C#: Dictionary, Hashtable.)
  • Lista ordenada de valores. (Análogo a los arreglos en C#).
Ejemplo de la representación de JSON:

{
"lenguajes" :
[
{ "nombre": "C#", "plataforma": ".NET" },
{ "nombre": "Java", "plataforma": "JEE" },
{ "nombre": "PHP", "plataforma": "ZEND" }
]
}

Aquí se observa un patrón interesante en la estructuración de los objetos JSON: el elemento (atributo) lenguajes es un contenedor (arreglo, o colección) de otros elementos anidados (los objetos con atributos nombre, y plataforma.)

3.2 La clase DataContractJsonSerializer

Sintaxis declarativa de DataContractJsonSerializer:

public sealed class DataContractJsonSerializer : XmlObjectSerializer

(Más adelante, en otros artículos, describiré la naturaleza hereditaria desde XMLObjectSerializer.)

Continuo con la descripción de esta clase. Según [1], esta clase pertenece al grupo de artefactos de la plataforma .NET para el intercambio de datos entre un cliente y un servicio (interoperabilidad). Se suma también el soporte nativo para la serialización/deserialización de tanto de colecciones como de objetos desde y hacia JSON. Esta clase es dependiente de los tipos (clases, interfaces, y estructuras) localizados en los assemblies System.ServiceModel.Web [8] y System.Runtime.Serialization [9].

En la introducción de esta sección he especificado que para crear una instancia de DataContractJsonSerializer es necesario especificar el tipo de dato (invocando a GetType -cfr. El Método GetType y el Operador typeof en C#-) a serializar/deserializar. Una vez instanciado un objeto, pasamos a invocar al método WriteObject (sobrecargado)  [11] para serializar el estado del objeto.

Continuando, el método ReadObject (sobrecargado) [12] lo usamos para la operación inversa, es decir, para deserializar (unmarshalling) el objeto desde una fuente de datos JSON. El tipo del objeto devuelto por ReadObject es object, ergo, es necesario hacer el casting correspondiente para el tipo que esperamos manipular.

Recurramos a la sección práctica para concretar este método de serialización.

4. Práctica: Código Fuente C#

En este ejemplo vamos a serializar los elementos de una lista (List) de elementos tipo string. Una vez serializado, veremos el resulado con notación JSON:


Compilación:


  1. csc /target:exe SerializacionJson.cs

Ejecución:


  1. .\SerializacionJson.exe

Resultado:
Resultado ejecución .\SerializacionJson.exe
Figura 1. Resultado ejecución .\SerializacionJson.exe.

5. Conclusiones

Conocimos los métodos WriteObject y ReadObject de la clase DataContractJsonSerializer, útiles para serialización y deserialización desde y hacia la notación JSON. Conocimos que JSON es un estándar para representar datos a modo de colecciones y listas secuenciales. Concretamos en la sección práctica el uso de los métodos anteriores para demostrar la serialización de un objeto List.

6. Glosario

  • Deserialización
  • Estándar JSON
  • JSON
  • Notación
  • Serialización

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.
[2]: JSON - http://json.org/
[3]: JSON, the free encyclopedia - https://en.wikipedia.org/wiki/Json
[4]: Extract, transform, load, the free encyclopedia - https://en.wikipedia.org/wiki/Extract,_transform,_load
[5]: Parsing, the free encyclopedia - https://en.wikipedia.org/wiki/Parsing
[6]: DataContractJsonSerializer Class (System.Runtime.Serialization.Json) - http://msdn.microsoft.com/en-us/library/system.runtime.serialization.json.datacontractjsonserializer%28v=vs.110%29.aspx
[7]: An Introduction to JavaScript Object Notation (JSON) in JavaScript and .NET - http://msdn.microsoft.com/en-us/library/bb299886.aspx
[8]: System.ServiceModel.Web Namespace () - http://msdn.microsoft.com/en-us/library/system.servicemodel.web%28v=vs.110%29.aspx
[9]: System.Runtime.Serialization Namespace () - http://msdn.microsoft.com/en-us/library/system.runtime.serialization%28v=vs.110%29.aspx
[10]: El Método GetType y el Operador typeof en C# | OrtizOL - Experiencias Construcción Software (xCSw) - http://ortizol.blogspot.com/2014/04/el-metodo-gettype-y-el-operador-typeof.html
[11]: DataContractJsonSerializer.WriteObject Method (System.Runtime.Serialization.Json) - http://msdn.microsoft.com/en-us/library/system.runtime.serialization.json.datacontractjsonserializer.writeobject%28v=vs.110%29.aspx
[12]: DataContractJsonSerializer.ReadObject Method (System.Runtime.Serialization.Json) - http://msdn.microsoft.com/en-us/library/system.runtime.serialization.json.datacontractjsonserializer.readobject%28v=vs.110%29.aspx


J