serialize serializar net example deserializar c# .net xml-serialization

c# - serializar - ¿Hay alguna razón por la que una clase base decorada con XmlInclude todavía genere una excepción de tipo desconocido cuando se serializa?



system xml serialization xmlserializer vb net (1)

Simplificaré el código para ahorrar espacio, pero lo que se presenta ilustra el problema central.

Tengo una clase que tiene una propiedad que es un tipo base. Hay 3 clases derivadas que se podrían asignar a esa propiedad.

Si asigno cualquiera de las clases derivadas al contenedor e intento serializar el contenedor, el XmlSerializer arroja el temido:

"No se esperaba el tipo x. Use el atributo XmlInclude o SoapInclude para especificar tipos que no se conocen estáticamente".

Sin embargo, mi clase base ya está decorada con ese atributo, por lo que creo que debe haber un requisito "oculto" adicional.

La parte realmente extraña es que el serializador WCF predeterminado no tiene problemas con esta jerarquía de clases.

La clase Container

[DataContract] [XmlRoot(ElementName = "TRANSACTION", Namespace = Constants.Namespace)] public class PaymentSummaryRequest : CommandRequest { [DataMember] public PaymentSummary Summary { get; set; } public PaymentSummaryRequest() { Mechanism = CommandMechanism.PaymentSummary; } }

La clase base

[DataContract] [XmlInclude(typeof(xPaymentSummary))] [XmlInclude(typeof(yPaymentSummary))] [XmlInclude(typeof(zPaymentSummary))] [KnownType(typeof(xPaymentSummary))] [KnownType(typeof(yPaymentSummary))] [KnownType(typeof(zPaymentSummary))] public abstract class PaymentSummary { }

Una de las clases derivadas

[DataContract] public class xPaymentSummary : PaymentSummary { }

El código de serialización

var serializer = new XmlSerializer(typeof(PaymentSummaryRequest)); serializer.Serialize(Console.Out,new PaymentSummaryRequest{Summary = new xPaymentSummary{}});

La excepción

System.InvalidOperationException: hubo un error al generar el documento XML. ---> System.InvalidOperationException: no se esperaba el tipo xPaymentSummary. Utilice el atributo XmlInclude o SoapInclude para especificar los tipos que no se conocen estáticamente. a

Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterPaymentSummaryRequest.Write13_PaymentSummary (String n, String ns, PaymentSummary o, Boolean isNullable, Boolean needType) en

Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterPaymentSummaryRequest.Write14_PaymentSummaryRequest (String n, String ns, PaymentSummaryRequest o, Boolean isNullable, Boolean needType) en

Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterPaymentSummaryRequest.Write15_TRANSACTION (Object o) --- Fin de la pila de excepción interna trace --- at

System.Xml.Serialization.XmlSerializer.Serialize (XmlWriter xmlWriter, Object o, espacios de nombres XmlSerializerNamespaces, String encodingStyle, String id) en

System.Xml.Serialization.XmlSerializer.Serialize (TextWriter textWriter, Object o, espacios de nombres de XmlSerializerNamespaces)
en UserQuery.RunUserAuthoredQuery () en c: / Users / Tedford / AppData / Local / Temp / uqacncyo.0.cs: línea 47


El problema que está viendo es que PaymentSummaryRequest está configurando el espacio de nombres. Puede eliminar el Espacio de nombres o agregar un Espacio de nombres a la clase PaymentSummary :

[XmlRoot(Namespace = Constants.Namespace)] [XmlInclude(typeof(xxxPaymentSummary))] public abstract class PaymentSummary { }

Como @Tedford menciona en su comentario a continuación, el espacio de nombre solo es necesario cuando se usan tipos derivados.

Al generar el ensamblaje de serialización XML, parece que, como el nodo raíz tiene un espacio de nombres establecido y la clase base no, no incluye la lógica de inclusión XML en el ensamblaje de serialización generado.

Otro enfoque para resolver el problema sería eliminar las declaraciones del espacio de nombres de las clases mismas y especificar el espacio de nombres en el constructor de XmlSerializer :

var serializer = new XmlSerializer( typeof(PaymentSummaryRequest), Constants.Namespace );