System.Xml.Serialization.XmlSerializer (clase)

En este artículo se proporcionan comentarios adicionales a la documentación de referencia de esta API.

La serialización XML es el proceso mediante el cual los campos y propiedades públicos de un objeto se convierten a un formato de serie (en este caso, XML) a efectos de almacenamiento o transporte. La deserialización vuelve a crear el objeto en su estado original a partir de la salida XML. Puede considerar la serialización como una manera de guardar el estado de un objeto en un flujo o búfer. Por ejemplo, ASP.NET usa la clase XmlSerializer para codificar mensajes de servicio web XML.

Los datos de los objetos se describen utilizando construcciones de lenguaje de programación como, por ejemplo, clases, campos, propiedades, tipos primitivos, matrices e incluso XML incrustado en forma de objetos XmlElement o XmlAttribute. Existe la opción de crear clases propias, anotadas con atributos, o de utilizar la herramienta de definición de esquema XML(Xsd.exe) para generar las clases de acuerdo con un documento de definición de esquema XML (XSD) existente. Si tiene un esquema XML, puede ejecutar Xsd.exe para generar un conjunto de clases fuertemente tipadas para el esquema y que se anoten con atributos para adherirse al esquema cuando se serializan.

Para transferir datos entre objetos y código XML, se necesita una asignación de las construcciones del lenguaje de programación al esquema XML y del esquema XML a las construcciones del lenguaje de programación. XmlSerializer y herramientas relacionadas como Xsd.exe proporcionan el puente entre estas dos tecnologías tanto en tiempo de diseño como en tiempo de ejecución. En tiempo de diseño, use Xsd.exe para generar un documento de esquema XML (.xsd) a partir de las clases personalizadas o para generar clases a partir de un esquema determinado. En cualquier caso, las clases se anotan con atributos personalizados para indicar a XmlSerializer cómo asignar entre el sistema de esquema XML y Common Language Runtime. En tiempo de ejecución, las instancias de las clases se pueden serializar en documentos XML que siguen el esquema especificado. Del mismo modo, estos documentos XML se pueden deserializar en objetos en tiempo de ejecución. Tenga en cuenta que el esquema XML es opcional y no es necesario en tiempo de diseño o tiempo de ejecución.

Control del código XML generado

Para controlar el código XML generado, puede aplicar atributos especiales a clases y miembros. Por ejemplo, para especificar un nombre de elemento XML diferente, aplique un objeto XmlElementAttribute a un campo o propiedad público, y establezca la propiedad ElementName. Para obtener una lista completa de atributos similares, vea Atributos que controlan la serialización XML. También puede implementar la interfaz IXmlSerializable para controlar la salida XML.

Si el XML generado se debe ajustar a la sección 5 del documento del World Wide Consortium, Protocolo simple de acceso a objetos (SOAP) 1.1, debe construir XmlSerializer con XmlTypeMapping. Para controlar más el XML codificado con SOAP, use los atributos mencionados en Atributos que controlan la serialización codificada con SOAP.

Con XmlSerializer puede aprovechar las ventajas de trabajar con clases fuertemente tipadas y seguir teniendo la flexibilidad de XML. Al usar campos o propiedades de tipo XmlElement, XmlAttribute o XmlNode en las clases fuertemente tipadas, puede leer partes del documento XML directamente en objetos XML.

Si trabaja con esquemas XML extensibles, también puede usar los atributos XmlAnyElementAttribute y XmlAnyAttributeAttribute para serializar y deserializar elementos o atributos que no se encuentran en el esquema original. Para usar los objetos, aplique una instancia de XmlAnyElementAttribute a un campo que devuelva una matriz de objetos XmlElement, o bien aplique XmlAnyAttributeAttribute a un campo que devuelva una matriz de objetos XmlAttribute.

Si una propiedad o un campo devuelve un objeto complejo como, por ejemplo, una matriz o una instancia de clase, XmlSerializer lo convierte a un elemento anidado en el documento XML principal. Por ejemplo, la primera clase del código siguiente devuelve una instancia de la segunda clase.

Public Class MyClass
    Public MyObjectProperty As MyObject
End Class

Public Class MyObject
    Public ObjectName As String
End Class
public class MyClass
{
    public MyObject MyObjectProperty;
}
public class MyObject
{
    public string ObjectName;
}

La salida XML serializada tiene este aspecto:

<MyClass>
  <MyObjectProperty>
  <ObjectName>My String</ObjectName>
  </MyObjectProperty>
</MyClass>

Si un esquema incluye un elemento opcional (minOccurs = "0"), o un valor predeterminado, tiene dos opciones. Una opción consiste en usar System.ComponentModel.DefaultValueAttribute para especificar el valor predeterminado, como se muestra en el código siguiente.

Public Class PurchaseOrder
    <System.ComponentModel.DefaultValueAttribute ("2002")> _
    Public Year As String
End Class
public class PurchaseOrder
{
    [System.ComponentModel.DefaultValueAttribute ("2002")]
    public string Year;
}

Otra opción consiste en usar un patrón especial para crear un campo booleano reconocido por XmlSerializery aplicar XmlIgnoreAttribute al campo. El patrón se crea con el formato propertyNameSpecified. Por ejemplo, si hay un campo denominado "MyFirstName", también tendría que crear un campo denominado "MyFirstNameSpecified" que indica a XmlSerializer si se debe generar el elemento XML denominado "MyFirstName". Esta implementación se muestra en el ejemplo siguiente.

Public Class OptionalOrder
    ' This field's value should not be serialized
    ' if it is uninitialized.
    Public FirstOrder As String

    ' Use the XmlIgnoreAttribute to ignore the
    ' special field named "FirstOrderSpecified".
    <System.Xml.Serialization.XmlIgnoreAttribute> _
    Public FirstOrderSpecified As Boolean
End Class
public class OptionalOrder
{
    // This field should not be serialized
    // if it is uninitialized.
    public string FirstOrder;

    // Use the XmlIgnoreAttribute to ignore the
    // special field named "FirstOrderSpecified".
    [System.Xml.Serialization.XmlIgnoreAttribute]
    public bool FirstOrderSpecified;
}

Invalidación de la serialización predeterminada

También puede invalidar la serialización de cualquier conjunto de objetos y sus campos y propiedades si crea uno de los atributos adecuados y lo agrega a una instancia de la clase XmlAttributes. La invalidación de la serialización de esta manera tiene dos usos: en primer lugar, puede controlar y aumentar la serialización de objetos que se encuentran en un archivo DLL, incluso si no tiene acceso al origen; en segundo lugar, puede crear un conjunto de clases serializables, pero serializar los objetos de varias maneras. Para más información, vea la clase XmlAttributeOverrides y Procedimiento para controlar la serialización de clases derivadas.

Para serializar un objeto, llame al método Serialize. Para deserializar un objeto, llame al método Deserialize.

Para agregar espacios de nombres XML a un documento XML, vea XmlSerializerNamespaces.

Nota:

XmlSerializer proporciona un tratamiento especial a las clases que implementan IEnumerable o ICollection. Una clase que implementa IEnumerable debe implementar un método Add público que requiere un solo parámetro. El parámetro del método Add debe ser del mismo tipo que se devuelve de la propiedad Current en el valor devuelto desde GetEnumerator, o bien una de las bases de ese tipo. Una clase que implementa ICollection (como CollectionBase) además de IEnumerable debe tener una propiedad indexada Item pública (un indizador en C#) que toma un número entero y debe tener una propiedad pública Count de tipo entero. El parámetro pasado al método Add debe ser del mismo tipo que el que se devuelve de la propiedad Item, o bien una de las bases de ese tipo. Para las clases que implementan ICollection, los valores que se han de serializar se recuperan de la propiedad indexada Item, no mediante una llamada a GetEnumerator.

Debe tener permiso para escribir en el directorio temporal (tal como se define en la variable de entorno TEMP) para deserializar un objeto.

Ensamblados generados dinámicamente

Para aumentar el rendimiento, la infraestructura de serialización XML genera dinámicamente ensamblados para serializar y deserializar tipos especificados. La infraestructura busca y reutiliza esos ensamblados. Este comportamiento solo se produce cuando se usan los constructores siguientes:

XmlSerializer.XmlSerializer(Type)

XmlSerializer.XmlSerializer(Type, String)

Si usa cualquiera de los otros constructores, se generan varias versiones del mismo ensamblado y nunca se descargan, lo que produce una pérdida de memoria y un rendimiento deficiente. La solución más sencilla consiste en usar uno de los dos constructores mencionados anteriormente. De lo contrario, debe almacenar en caché los ensamblados en una instancia de Hashtable, como se muestra en el ejemplo siguiente.

Hashtable serializers = new Hashtable();

// Use the constructor that takes a type and XmlRootAttribute.
XmlSerializer s = new XmlSerializer(typeof(MyClass), myRoot);

// Implement a method named GenerateKey that creates unique keys
// for each instance of the XmlSerializer. The code should take
// into account all parameters passed to the XmlSerializer
// constructor.
object key = GenerateKey(typeof(MyClass), myRoot);

// Check the local cache for a matching serializer.
XmlSerializer ser = (XmlSerializer)serializers[key];
if (ser == null)
{
    ser = new XmlSerializer(typeof(MyClass), myRoot);
    // Cache the serializer.
    serializers[key] = ser;
}

// Use the serializer to serialize or deserialize.
Dim serializers As New Hashtable()

' Use the constructor that takes a type and XmlRootAttribute.
Dim s As New XmlSerializer(GetType([MyClass]), myRoot)

' Implement a method named GenerateKey that creates unique keys
' for each instance of the XmlSerializer. The code should take
' into account all parameters passed to the XmlSerializer
' constructor.
Dim key As Object = GenerateKey(GetType([MyClass]), myRoot)

' Check the local cache for a matching serializer.
Dim ser As XmlSerializer = CType(serializers(key), XmlSerializer)

If ser Is Nothing Then
    ser = New XmlSerializer(GetType([MyClass]), myRoot)
    ' Cache the serializer.
    serializers(key) = ser
End If

' Use the serializer to serialize or deserialize.

Serialización de ArrayList y lista genérica

XmlSerializer no puede serializar ni deserializar lo siguiente:

Serialización de enumeraciones de Long sin signo

No se puede crear una instancia de XmlSerializer para serializar una enumeración si se cumplen las condiciones siguientes: la enumeración es de tipo long sin signo (ulong en C#) y contiene cualquier miembro con un valor superior a 9.223.372.036.854.775.807. Por ejemplo, no se puede serializar lo siguiente.

public enum LargeNumbers: ulong
{
    a = 9223372036854775808
}
// At run time, the following code will fail.
xmlSerializer mySerializer=new XmlSerializer(typeof(LargeNumbers));

Tipos obsoletos

La XmlSerializer clase no serializa los objetos marcados como [Obsolete].