XmlSerializer – Hubo un error que refleja el tipo

Utilizando C # .NET 2.0, tengo una clase de datos compuesta que tiene el atributo [Serializable] . Estoy creando una clase XMLSerializer y pasando eso al constructor:

 XmlSerializer serializer = new XmlSerializer(typeof(DataClass)); 

Estoy recibiendo una excepción diciendo:

Hubo un error que refleja el tipo.

Dentro de la clase de datos hay otro objeto compuesto. ¿Esto también necesita tener el atributo [Serializable] , o al tenerlo en el objeto superior, lo aplica recursivamente a todos los objetos dentro?

Mire la excepción interna que está recibiendo. Le indicará qué campo / propiedad está teniendo problemas para serializar.

Puede excluir campos / propiedades de la serialización xml decorándolos con el atributo [XmlIgnore] .

No creo que XmlSerializer use el atributo [Serializable] , así que dudo que ese sea el problema.

Recuerde que las clases serializadas deben tener constructores predeterminados (es decir, sin parámetros). Si no tienes ningún constructor, está bien; pero si tienes un constructor con un parámetro, necesitarás agregar el predeterminado también.

Tuve un problema similar, y resultó que el serializador no podía distinguir entre 2 clases que tenía con el mismo nombre (una era una subclase de la otra). La excepción interna se veía así:

‘Types BaseNamespace.Class1’ y ‘BaseNamespace.SubNamespace.Class1’ usan el nombre de tipo XML, ‘Class1’, del espacio de nombres ”. Use atributos XML para especificar un nombre XML único y / o espacio de nombre para el tipo.

Donde BaseNamespace.SubNamespace.Class1 es una subclase de BaseNamespace.Class1.

Lo que tenía que hacer era agregar un atributo a una de las clases (agregué a la clase base):

 [XmlType("BaseNamespace.Class1")] 

Nota: si tiene más capas de clases, también necesita agregarles un atributo.

También tenga en cuenta que XmlSerializer no puede serializar propiedades abstractas. Consulte mi pregunta aquí (a la que he agregado el código de la solución).

Serialización XML y tipos heredados

Las razones más comunes por mi:

  - the object being serialized has no parameterless constructor - the object contains Dictionary - the object has some public Interface members 

Todos los objetos en el gráfico de serialización deben ser serializables.

Como XMLSerializer es un blackbox, verifique estos enlaces si desea depurar aún más el proceso de serialización.

Cambiar dónde XmlSerializer genera ensamblajes temporales

CÓMO PARA: Depurar en un ensamblado generado .NET XmlSerializer

Si necesita manejar atributos específicos (es decir, Diccionario, o cualquier clase), puede implementar la interfaz IXmlSerialiable , que le permitirá más libertad a costa de una encoding más detallada .

 public class NetService : IXmlSerializable { #region Data public string Identifier = String.Empty; public string Name = String.Empty; public IPAddress Address = IPAddress.None; public int Port = 7777; #endregion #region IXmlSerializable Implementation public XmlSchema GetSchema() { return (null); } public void ReadXml(XmlReader reader) { // Attributes Identifier = reader[XML_IDENTIFIER]; if (Int32.TryParse(reader[XML_NETWORK_PORT], out Port) == false) throw new XmlException("unable to parse the element " + typeof(NetService).Name + " (badly formatted parameter " + XML_NETWORK_PORT); if (IPAddress.TryParse(reader[XML_NETWORK_ADDR], out Address) == false) throw new XmlException("unable to parse the element " + typeof(NetService).Name + " (badly formatted parameter " + XML_NETWORK_ADDR); } public void WriteXml(XmlWriter writer) { // Attributes writer.WriteAttributeString(XML_IDENTIFIER, Identifier); writer.WriteAttributeString(XML_NETWORK_ADDR, Address.ToString()); writer.WriteAttributeString(XML_NETWORK_PORT, Port.ToString()); } private const string XML_IDENTIFIER = "Id"; private const string XML_NETWORK_ADDR = "Address"; private const string XML_NETWORK_PORT = "Port"; #endregion } 

Hay un artículo interesante, que muestra una forma elegante de implementar una forma sofisticada de “extender” el XmlSerializer.


El artículo dice:

IXmlSerializable está cubierto en la documentación oficial, pero la documentación indica que no está destinado para uso público y no proporciona información más allá de eso. Esto indica que el equipo de desarrollo quería reservar el derecho de modificar, desactivar o incluso eliminar completamente este enlace de extensibilidad en el futuro. Sin embargo, siempre que esté dispuesto a aceptar esta incertidumbre y enfrentar posibles cambios en el futuro, no hay razón alguna para no aprovecharla.

Debido a esto, sugiero implementar sus propias clases IXmlSerializable , para evitar implementaciones demasiado complicadas.

… podría ser sencillo implementar nuestra clase personalizada de XmlSerializer utilizando la reflexión.

Descubrí que la clase de diccionario en .Net 2.0 no se puede serializar mediante XML, pero se serializa bien cuando se utiliza la serialización binaria.

Encontré un trabajo por aquí .

Hace poco recibí esto en una clase parcial de referencia web al agregar una nueva propiedad. La clase autogenerada estaba agregando los siguientes atributos.

  [System.Xml.Serialization.XmlElementAttribute(Order = XX)] 

Necesitaba agregar un atributo similar con un orden uno más alto que el último en la secuencia generada automáticamente y esto lo solucionó para mí.

Yo también pensé que el atributo Serializable tenía que estar en el objeto, pero a menos que esté siendo un novato completo (estoy en el medio de una sesión de encoding a última hora de la noche) los siguientes trabajos de SnippetCompiler :

 using System; using System.IO; using System.Xml; using System.Collections.Generic; using System.Xml.Serialization; public class Inner { private string _AnotherStringProperty; public string AnotherStringProperty { get { return _AnotherStringProperty; } set { _AnotherStringProperty = value; } } } public class DataClass { private string _StringProperty; public string StringProperty { get { return _StringProperty; } set{ _StringProperty = value; } } private Inner _InnerObject; public Inner InnerObject { get { return _InnerObject; } set { _InnerObject = value; } } } public class MyClass { public static void Main() { try { XmlSerializer serializer = new XmlSerializer(typeof(DataClass)); TextWriter writer = new StreamWriter(@"c:\tmp\dataClass.xml"); DataClass clazz = new DataClass(); Inner inner = new Inner(); inner.AnotherStringProperty = "Foo2"; clazz.InnerObject = inner; clazz.StringProperty = "foo"; serializer.Serialize(writer, clazz); } finally { Console.Write("Press any key to continue..."); Console.ReadKey(); } } } 

Me imagino que el XmlSerializer está utilizando la reflexión sobre las propiedades públicas.

Tuve una situación en la que el orden era el mismo para dos elementos en una fila

 [System.Xml.Serialization.XmlElementAttribute(IsNullable = true, Order = 0, ElementName = "SeriousInjuryFlag")] 

…. algún código …

 [System.Xml.Serialization.XmlElementAttribute(IsNullable = true, Order = 0, ElementName = "AccidentFlag")] 

Cuando cambié el código para incrementar el orden por uno para cada Propiedad nueva en la clase, el error desapareció.

Acabo de recibir el mismo error y descubrí que el problema era una propiedad de tipo IEnumerable . Parece que IEnumerable no se puede serializar directamente.

También tenga en cuenta que no puede serializar controles de interfaz de usuario y que cualquier objeto que desee pasar al portapapeles debe ser serializable, de lo contrario no se puede pasar a otros procesos.

He estado usando la clase NetDataSerialiser para serializar mis clases de dominio. Clase NetDataContractSerializer .

Las clases de dominio se comparten entre el cliente y el servidor.

[System.Xml.Serialization.XmlElementAttribute (“strFieldName”, Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]

//O

[XmlIgnore] string [] strFielsName {get; set;}

Tuve el mismo problema y en mi caso el objeto tenía una ReadOnlyCollection. Una colección debe implementar el método Add para ser serializable.