image

Buenas,

hoy toca poner un ejemplo de código bastante simple, pero que puede traerte un par de dolores de cabeza si no sabes por donde empezar. La idea es simple:

Incluir un archivo XML en una aplicación METRO y des serializar el mismo para trabajar en una aplicación.

Esto que parece tan simple, se complica un poco en METRO ya que los tan namespaces tan populares como System.IO y otros con los que estamos acostumbrados a trabajar ya no están disponibles.

Si a eso le sumamos, que la mayoría de las acciones son en modo asíncrono, pues la programación cambia bastante. Pero claro, Visual Studio 11 llega a nuestro rescate con las nuevas sentencias ASYNC y AWAIT que realmente nos ayudan a programar en modo asíncrono.

Vamos por partes, en el proyecto de ejemplo tenemos una clase sample data con 2 propiedades definidas como el siguiente ejemplo:

   1: namespace Application1

   2: {

   3:     public class SampleData

   4:     {

   5:         public string Id { get; set; }

   6:         public string Name { get; set; }

   7:     }

   8: }

Luego incluimos un archivo XML dentro de una carpeta XML, con la siguiente información dentro del mismo

   1: <?xml version="1.0"?>

   2: <ArrayOfSampleData 

   3:    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 

   4:    xmlns:xsd="http://www.w3.org/2001/XMLSchema">

   5:   <SampleData>

   6:     <Id>El</Id>

   7:     <Name>Bruno</Name>

   8:   </SampleData>

   9: </ArrayOfSampleData>

Así a simple vista, podemos ver que este XML es una serialización de un Array de elementos de tipo SampleData.

Luego queda la parte interesante, que es leer de este archivo. El siguiente código muestra un ejemplo donde la función LoadSampleData() retorna una colección de elementos del tipo SampleData leyendo un archivo llamado “data.xml” de un directorio de la aplicación llamado “XML“.

   1: private async void BtnGetClick(object sender, RoutedEventArgs e)

   2: {

   3:     var collection = LoadSampleData();

   4:     await collection;

   5:     var item = collection.Result[0];

   6:     txtId.Text = item.Id;

   7:     txtName.Text = item.Name;

   8: }

   9:  

  10: public async Task<ObservableCollection<SampleData>> LoadSampleData()

  11: {

  12:     var storageFolder = await Package.Current.InstalledLocation.GetFolderAsync("XML");

  13:     var sampleDataItems = await LoadFromXmlFile<ObservableCollection<SampleData>>("data.xml", storageFolder);

  14:     return sampleDataItems;

  15: }

Un par de detalles a tener en cuenta es que la función LoadSampleData() está definida con un prefijo async, que denota que la misma se puede ejecutar de modo asíncrono. Esto es posible ya que la lectura del directorio de trabajo (línea 12) se realiza en modo asíncrono.

En este punto merecen un especial detalle las sentencias donde para la ejecución de la función asíncrona se utiliza await. La forma más simple de definir a await es pensar en que con esta sentencia podremos llamar a funciones asíncronas y cuando se terminen las mismas, await retornará al flujo de trabajo indicado.

Ahora vamos a la parte interesante que es la desserialización del archivo XML. Para esto utilizamos la función LoadFromXmlFile que internamente, una vez que ha leido el contenido del archivo, des serializa el mismo en memoria (líneas 3 a 6). El siguiente código muestra un ejemplo de este funcionamiento:

   1: public static async Task<T> LoadFromXmlFile<T>(string fileName, StorageFolder folder = null)

   2: {

   3:     var xmlString = await ReadFromFile(fileName, folder);

   4:     var ms = new MemoryStream(UTF8Encoding.UTF8.GetBytes(xmlString));

   5:     var ser = new XmlSerializer(typeof(T));

   6:     T result = (T)ser.Deserialize(ms);

   7:     return result;

   8: }

   9:  

  10: public static async Task<string> ReadFromFile(string fileName, StorageFolder folder = null)

  11: {

  12:     folder = folder ?? ApplicationData.Current.LocalFolder;

  13:     var file = await folder.GetFileAsync(fileName);

  14:     using (var accessStream = await file.OpenAsync(FileAccessMode.Read))

  15:     {

  16:         using (var inStream = accessStream.GetInputStreamAt(0))

  17:         {

  18:             using (var reader = new DataReader(inStream))

  19:             {

  20:                 await reader.LoadAsync((uint)accessStream.Size);

  21:                 var data = reader.ReadString((uint)accessStream.Size);

  22:                 reader.DetachStream();

  23:                 return data;

  24:             }

  25:         }

  26:     }

  27: }

 

Voy a intentar separar el código del pedazo de POC que estoy construyendo y después de un poco de refactoring subiré un ejemplo más completo.

 

Saludos @ Home

El Bruno

image image image

Leave a comment

Discover more from El Bruno

Subscribe now to keep reading and get access to the full archive.

Continue reading