c# .net xml serialization .net-2.0

c# - XmlSerializer-Hubo un error que refleja el tipo



.net serialization (16)

Al usar C # .NET 2.0, tengo una clase de datos compuestos que tiene el atributo [Serializable] . Estoy creando una clase de XMLSerializer y la paso al constructor:

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

Estoy recibiendo una excepción que dice:

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?


Acabo de recibir el mismo error y descubrí que una propiedad de tipo IEnumerable<SomeClass> era el problema. Parece que IEnumerable no puede ser serializado directamente.


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

Encontré un trabajo por here .


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.


Las razones más comunes por mí:

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


Mira la excepción interna que estás recibiendo. Le dirá qué campo / propiedad tiene 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.


Recientemente obtuve esto en una clase parcial de referencia web al agregar una nueva propiedad. La clase generada automáticamente 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 arreglé para mí.


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


Si necesita manejar atributos específicos (es decir, el Diccionario o cualquier clase), puede implementar la interfaz IXmlSerialiable , que le permitirá más libertad a costa de una codificación 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 article interesante que muestra una manera 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á destinada para uso público y no proporciona información más allá de eso. Esto indica que el equipo de desarrollo quiso reservarse el derecho de modificar, deshabilitar o incluso eliminar por completo este gancho de extensibilidad en el camino. Sin embargo, mientras esté dispuesto a aceptar esta incertidumbre y lidiar con posibles cambios en el futuro, no hay razón alguna por la que no pueda aprovecharla.

Debido a esto, sugiero que implementes tus propias clases IXmlSerializable , para evitar implementaciones demasiado complicadas.

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


También tenga en cuenta que XmlSerializer no puede serializar propiedades abstractas. Vea mi pregunta here (a la que le agregué el código de la solución).

here


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



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


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 los atributos XML para especificar un nombre XML único y / o espacio de nombres 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.


Tuve una situación en la que la Orden era la misma para dos elementos seguidos

[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 pedido en uno por cada nueva propiedad en la clase, el error desapareció.


Yo también pensé que el atributo Serializable tenía que estar en el objeto, pero a menos que esté siendo un noob completo (estoy en medio de una sesión de codificación nocturna) los siguientes trabajos del 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.


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

//O

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