Almacenamiento y serialización de documentos

Microsoft .NET Framework proporciona un potente entorno para crear y mostrar documentos de alta calidad. Las características mejoradas que admiten tanto los documentos fijos como los documentos dinámicos, los controles de visualización avanzados y la combinación con las potentes capacidades gráficas en 2D y 3D, hacen que las aplicaciones .NET Framework alcancen un nuevo nivel de calidad y experiencia de usuario. Poder administrar con flexibilidad una representación en memoria de un documento es una característica clave de .NET Framework. Y poder guardar y cargar eficazmente los documentos desde un almacén de datos es una necesidad para casi cualquier aplicación. El proceso de convertir un documento de una representación en memoria interna a un almacén de datos externo se denomina “serialización”. El proceso inverso de leer un almacén de datos y volver a crear la instancia en memoria original se denomina “deserialización”.

Acerca de la serialización de documentos

Lo ideal es que el proceso de serialización y deserialización de un documento desde la memoria y de vuelta hacia esta sea transparente para la aplicación. La aplicación llama a un método serializador de "escritura" para guardar el documento, mientras que un método deserializador de "lectura" obtiene acceso al almacén de datos y vuelve a crear la instancia original en memoria. En general, la aplicación no se encarga del formato específico en que se almacenan los datos, siempre que el proceso de serialización y deserialización vuelva a crear el documento en su forma original.

Las aplicaciones suelen proporcionar varias opciones de serialización que permiten al usuario guardar documentos en distintos soportes o en un formato diferente. Por ejemplo, una aplicación podría ofrecer la opción "Guardar como" para almacenar un documento en un archivo de disco, una base de datos o un servicio web. De forma similar, diferentes serializadores podrían almacenar el documento en formatos diferentes, por ejemplo, HTML, RTF, XML, XPS o, como alternativa, un formato de otro fabricante. Para la aplicación, la serialización define una interfaz que aísla los detalles del soporte de almacenamiento dentro de la implementación de cada serializador concreto. Además de las ventajas de encapsular los detalles de almacenamiento, las API System.Windows.Documents.Serialization de .NET Framework proporcionan varias características importantes.

Características de los serializadores de documentos de .NET Framework 3.0

  • El acceso directo a los objetos de documento de alto nivel (árbol lógico y elementos visuales) permite el almacenamiento eficiente de contenido paginado, elementos 2D o 3D, imágenes, elementos multimedia, hipervínculos, anotaciones y otro contenido de compatibilidad.

  • Funcionamiento sincrónico y asincrónico.

  • Compatibilidad con los serializadores de complemento con funciones mejoradas:

    • Acceso a todo el sistema para que lo usen todas las aplicaciones de .NET Framework.

    • Capacidad sencilla de detectar complementos de aplicaciones.

    • Implementación, instalación y actualización sencillas de complementos personalizados de terceros.

    • Compatibilidad de interfaz de usuario para opciones y configuración personalizadas en tiempo de ejecución.

Ruta de impresión XPS

La ruta de impresión XPS de Microsoft .NET Framework también proporciona un mecanismo extensible para escribir documentos a través de la salida de impresión. XPS sirve como un formato de archivo de documento y es el formato de cola de impresión nativo para Windows Vista. Los documentos de XPS pueden enviarse directamente a impresoras XPS compatibles sin necesidad de convertirlos a un formato intermedio. Consulte la Información general sobre impresión para obtener información adicional sobre las capacidades y opciones de salida de la ruta de impresión.

Serializadores de complemento

Las API System.Windows.Documents.Serialization proporcionan compatibilidad para serializadores de complemento y serializadores vinculados que se instalan independientemente de la aplicación, se enlazan en el tiempo de ejecución y permiten el acceso mediante el mecanismo de detección SerializerProvider. Los serializadores de complemento proporcionan ventajas mejoradas de facilidad de implementación y uso en todo el sistema. Los serializadores enlazados también pueden implementarse para entornos de confianza parcial, como las aplicaciones de navegador XAML (XBAP), en las que no se puede acceder a los serializadores de complemento. Los serializadores enlazados, que se basan en una implementación derivada de la clase SerializerWriter, se compilan y vinculan directamente en la aplicación. Tanto los serializadores de complemento como los serializadores vinculados funcionan mediante métodos y eventos públicos idénticos que facilitan el uso de uno o ambos tipos de serializadores en la misma aplicación.

Los serializadores de complemento ayudan a los desarrolladores de aplicaciones, al proporcionar extensibilidad a nuevos diseños de almacenamiento y formatos de archivo sin tener que programar directamente para cada formato potencial en tiempo de compilación. Los serializadores de complemento también benefician a los desarrolladores externos, al proporcionar un medio estandarizado para implementar, instalar y actualizar complementos accesibles por el sistema para formatos de archivo personalizados o de propietario.

Usar un serializador de complemento

Los serializadores de complemento son fáciles de usar. La clase SerializerProvider enumera un objeto SerializerDescriptor para cada complemento instalado en el sistema. La propiedad IsLoadable filtra los complementos instalados según la configuración actual y comprueba que la aplicación puede cargar y utilizar el serializador. La SerializerDescriptor también proporciona otras propiedades, como DisplayName y DefaultFileExtension, que la aplicación puede utilizar para preguntar al usuario que seleccione un serializador para un formato de salida disponible. Se proporciona un serializador de complemento predeterminado para XPS con .NET Framework y que siempre se enumera. Después de que el usuario seleccione un formato de salida, el método CreateSerializerWriter se utiliza para crear un SerializerWriter para el formato específico. El método SerializerWriter.Write puede entonces ser llamado para dar salida al flujo de documentos en el almacén de datos.

El siguiente ejemplo muestra una aplicación que usa el método SerializerProvider en una propiedad "PlugInFileFilter". PlugInFileFilter enumera los complementos instalados y genera una cadena de filtro con las opciones de archivo disponibles para una SaveFileDialog.

// ------------------------ PlugInFileFilter --------------------------
/// <summary>
///   Gets a filter string for installed plug-in serializers.</summary>
/// <remark>
///   PlugInFileFilter is used to set the SaveFileDialog or
///   OpenFileDialog "Filter" property when saving or opening files
///   using plug-in serializers.</remark>
private string PlugInFileFilter
{
    get
    {   // Create a SerializerProvider for accessing plug-in serializers.
        SerializerProvider serializerProvider = new SerializerProvider();
        string filter = "";

        // For each loadable serializer, add its display
        // name and extension to the filter string.
        foreach (SerializerDescriptor serializerDescriptor in
            serializerProvider.InstalledSerializers)
        {
            if (serializerDescriptor.IsLoadable)
            {
                // After the first, separate entries with a "|".
                if (filter.Length > 0)   filter += "|";

                // Add an entry with the plug-in name and extension.
                filter += serializerDescriptor.DisplayName + " (*" +
                    serializerDescriptor.DefaultFileExtension + ")|*" +
                    serializerDescriptor.DefaultFileExtension;
            }
        }

        // Return the filter string of installed plug-in serializers.
        return filter;
    }
}

Una vez que el usuario ha seleccionado un nombre de archivo de salida, en el ejemplo siguiente se muestra el uso del método CreateSerializerWriter para almacenar un documento determinado en un formato específico.

// Create a SerializerProvider for accessing plug-in serializers.
SerializerProvider serializerProvider = new SerializerProvider();

// Locate the serializer that matches the fileName extension.
SerializerDescriptor selectedPlugIn = null;
foreach ( SerializerDescriptor serializerDescriptor in
                serializerProvider.InstalledSerializers )
{
    if ( serializerDescriptor.IsLoadable &&
         fileName.EndsWith(serializerDescriptor.DefaultFileExtension) )
    {   // The plug-in serializer and fileName extensions match.
        selectedPlugIn = serializerDescriptor;
        break; // foreach
    }
}

// If a match for a plug-in serializer was found,
// use it to output and store the document.
if (selectedPlugIn != null)
{
    Stream package = File.Create(fileName);
    SerializerWriter serializerWriter =
        serializerProvider.CreateSerializerWriter(selectedPlugIn,
                                                  package);
    IDocumentPaginatorSource idoc =
        flowDocument as IDocumentPaginatorSource;
    serializerWriter.Write(idoc.DocumentPaginator, null);
    package.Close();
    return true;
}

Instalar serializadores de complemento

La clase SerializerProvider proporciona la interfaz de aplicación de nivel superior para la detección y el acceso al serializador de complementos. SerializerProvider busca y entrega a la aplicación una lista de los serializadores instalados y accesibles en el sistema. Los detalles de los serializadores instalados se definen mediante la configuración del registro. Los serializadores de complemento pueden agregarse al registro mediante el método RegisterSerializer o si aún no se ha instalado .NET Framework, el script de instalación del complemento puede establecer directamente los valores del registro por sí mismo. El método UnregisterSerializer se puede utilizar para eliminar un complemento previamente instalado, o la configuración del registro se puede restablecer de manera similar por un script de desinstalación.

Crear un serializador de complemento

Tanto los serializadores de complemento como los serializadores vinculados utilizan los mismos métodos y eventos públicos expuestos y, de forma similar, se pueden diseñar para funcionar de forma sincrónica o asincrónica. Existen tres pasos básicos que se suelen seguir para crear un serializador de complemento:

  1. Implementar y depurar el serializador en primer lugar como serializador vinculado. Crear inicialmente el serializador compilado y vinculado directamente en una aplicación de prueba proporciona acceso total a los puntos de interrupción y otros servicios de depuración útiles para realizar pruebas.

  2. Después de que el serializador esté completamente probado, se añade una interfaz ISerializerFactory para crear un complemento. La interfaz ISerializerFactory permite el acceso total a todos los objetos .NET Framework que incluyen el árbol lógico, los objetos UIElement, IDocumentPaginatorSource y los elementos Visual. Además, ISerializerFactory proporciona los mismos métodos y eventos sincrónicos y asincrónicos utilizados por los serializadores vinculados. Dado que los documentos de gran tamaño pueden tardar tiempo en generarse, se recomiendan las operaciones asincrónicas para mantener una interacción receptiva con el usuario y ofrecer la opción "Cancelar" si se produce algún problema con el almacén de datos.

  3. Después de crear el serializador del complemento, se implementa un script de instalación para distribuir e instalar (y desinstalar) el complemento (véase más arriba, "Instalar serializadores de complemento").

Vea también