Me encontré con algunos problemas al hacer la serialización C # XML que pensé que compartiría:
- No puede serializar elementos que sean de solo lectura (como KeyValuePairs)
- No se puede serializar un diccionario genérico. En su lugar, pruebe esta clase de contenedor (de http://weblogs.asp.net/pwelter34/archive/2006/05/03/444961.aspx ):
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
[XmlRoot("dictionary")]
public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, IXmlSerializable
{
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;
}
public void ReadXml(System.Xml.XmlReader reader)
{
XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));
bool wasEmpty = reader.IsEmptyElement;
reader.Read();
if (wasEmpty)
return;
while (reader.NodeType != System.Xml.XmlNodeType.EndElement)
{
reader.ReadStartElement("item");
reader.ReadStartElement("key");
TKey key = (TKey)keySerializer.Deserialize(reader);
reader.ReadEndElement();
reader.ReadStartElement("value");
TValue value = (TValue)valueSerializer.Deserialize(reader);
reader.ReadEndElement();
this.Add(key, value);
reader.ReadEndElement();
reader.MoveToContent();
}
reader.ReadEndElement();
}
public void WriteXml(System.Xml.XmlWriter writer)
{
XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));
foreach (TKey key in this.Keys)
{
writer.WriteStartElement("item");
writer.WriteStartElement("key");
keySerializer.Serialize(writer, key);
writer.WriteEndElement();
writer.WriteStartElement("value");
TValue value = this[key];
valueSerializer.Serialize(writer, value);
writer.WriteEndElement();
writer.WriteEndElement();
}
}
}
¿Alguna otra trampa de serialización XML por ahí?
c#
xml-serialization
kurious
fuente
fuente
Respuestas:
Otro gran problema: al generar XML a través de una página web (ASP.NET), no desea incluir la marca de orden de bytes Unicode . Por supuesto, las formas de usar o no usar la lista de materiales son casi las mismas:
MALO (incluye BOM):
BUENO:
Puede pasar explícitamente falso para indicar que no desea la lista de materiales. Observe la clara y obvia diferencia entre
Encoding.UTF8
yUTF8Encoding
.Los tres bytes BOM adicionales al principio son (0xEFBBBF) o (239 187 191).
Referencia: http://chrislaco.com/blog/troubleshooting-common-problems-with-the-xmlserializer/
fuente
XmlTextWriter
en .NET 2.0 o superior.Todavía no puedo hacer comentarios, así que comentaré la publicación de Dr8k y haré otra observación. Las variables privadas que se exponen como propiedades públicas de obtención / establecimiento, y se serializan / deserializan como tales a través de esas propiedades. Lo hicimos en mi antiguo trabajo todo el tiempo.
Sin embargo, una cosa a tener en cuenta es que si tiene alguna lógica en esas propiedades, la lógica se ejecuta, por lo que a veces, el orden de serialización realmente importa. Los miembros se ordenan implícitamente según cómo se ordenan en el código, pero no hay garantías, especialmente cuando se hereda otro objeto. Ordenarlos explícitamente es un dolor en la parte trasera.
Me quemé por esto en el pasado.
fuente
Al serializar en una cadena XML desde una secuencia de memoria, asegúrese de usar MemoryStream # ToArray () en lugar de MemoryStream # GetBuffer () o terminará con caracteres basura que no se deserializarán correctamente (debido al búfer adicional asignado).
http://msdn.microsoft.com/en-us/library/system.io.memorystream.getbuffer(VS.80).aspx
fuente
Si el serializador encuentra un miembro / propiedad que tiene una interfaz como su tipo, no se serializará. Por ejemplo, lo siguiente no se serializará en XML:
Aunque esto serializará:
fuente
IEnumerables<T>
que se generan a través de rendimientos de rendimiento no son serializables. Esto se debe a que el compilador genera una clase separada para implementar el rendimiento y esa clase no está marcada como serializable.fuente
No puede serializar propiedades de solo lectura. Debe tener un getter y un setter, incluso si nunca tiene la intención de utilizar la deserialización para convertir XML en un objeto.
Por la misma razón, no puede serializar propiedades que devuelven interfaces: el deserializador no sabría qué clase concreta instanciar.
fuente
Ah, aquí hay una buena: dado que el código de serialización XML se genera y se coloca en una DLL separada, no se produce ningún error significativo cuando hay un error en su código que rompe el serializador. Simplemente algo así como "no se puede localizar s3d3fsdf.dll". Agradable.
fuente
No se puede serializar un objeto que no tiene un constructor sin parámetros (ese solo lo mordió).
Y por alguna razón, de las siguientes propiedades, Value se serializa, pero no FullName:
Nunca pude averiguar por qué, simplemente cambié el valor a interno ...
fuente
double?
pero solodouble
?null
y, por lo tanto, no generará ningún XML cuando se serialiceUna cosa más a tener en cuenta: no puede serializar miembros de clase privados / protegidos si está utilizando la serialización XML "predeterminada".
Pero puede especificar una lógica de serialización XML personalizada que implemente IXmlSerializable en su clase y serializar cualquier campo privado que necesite / desee.
http://msdn.microsoft.com/en-us/library/system.xml.serialization.ixmlserializable.aspx
fuente
Si su ensamblaje generado por la serialización XML no está en el mismo contexto de carga que el código que intenta usarlo, se encontrará con errores increíbles como:
La causa de esto para mí fue un complemento cargado usando el contexto LoadFrom que tiene muchas desventajas al usar el contexto Load. Bastante divertido rastrearlo.
fuente
Es posible que tenga problemas para serializar objetos de tipo Color y / o Fuente.
Aquí están los consejos que me ayudaron:
http://www.codeproject.com/KB/XML/xmlsettings.aspx
http://www.codeproject.com/KB/cs/GenericXmlSerializition.aspx
fuente
Consulte " Soporte de enlace de atributos de lenguaje de definición de esquema XML avanzado " para obtener detalles sobre lo que admite el serializador XML y sobre cómo se admiten las características XSD compatibles.
fuente
Si intenta serializar una matriz,
List<T>
oIEnumerable<T>
que contiene instancias de subclases deT
, debe usar XmlArrayItemAttribute para enumerar todos los subtipos que se utilizan. De lo contrario, obtendrá un poco útilSystem.InvalidOperationException
en tiempo de ejecución cuando serialice.Aquí hay parte de un ejemplo completo de la documentación.
fuente
Las variables / propiedades privadas no se serializan en el mecanismo predeterminado para la serialización XML, pero sí en la serialización binaria.
fuente
Las propiedades marcadas con el
Obsolete
atributo no se serializan. No he probado con elDeprecated
atributo, pero supongo que actuaría de la misma manera.fuente
Realmente no puedo explicar esto, pero descubrí que esto no se serializará:
pero esto:
Y también vale la pena señalar que si está serializando a un memstream, es posible que desee buscar 0 antes de usarlo.
fuente
Tenga cuidado con los tipos de serialización sin una serialización explícita, puede generar demoras mientras .Net los construye. Descubrí esto recientemente mientras serializaba RSAParameters .
fuente
Si su XSD utiliza grupos de sustitución, entonces es probable que no pueda (des) serializarlo automáticamente. Tendrá que escribir sus propios serializadores para manejar este escenario.
P.ej.
En este ejemplo, un sobre puede contener mensajes. Sin embargo, el serializador predeterminado de .NET no distingue entre Message, ExampleMessageA y ExampleMessageB. Solo se serializará hacia y desde la clase de mensaje base.
fuente
Creo que esto también lo atrapa si está exponiendo a los miembros privados a través de propiedades públicas: los miembros privados no se serializan, por lo que los miembros públicos hacen referencia a valores nulos.
fuente