Y a-t-il une raison pour laquelle une classe de base décorée avec XmlInclude lancerait toujours une exception de type inconnu lorsqu’elle est sérialisée?

Je vais simplifier le code pour économiser de l’espace mais ce qui est présenté illustre bien le problème principal.

J’ai une classe qui a une propriété qui est un type de base. Il y a 3 classes dérivées qui pourraient être assignées à cette propriété.

Si j’atsortingbue l’une des classes dérivées au conteneur et que j’essaie de sérialiser le conteneur, le XmlSerializer lance le redoutable:

“Le type x n’était pas attendu. Utilisez l’atsortingbut XmlInclude ou SoapInclude pour spécifier les types qui ne sont pas connus de manière statique.”

Cependant, ma classe de base est déjà décorée avec cet atsortingbut, donc je pense qu’il doit y avoir une exigence supplémentaire “cachée”.

La partie vraiment étrange est que le sérialiseur WCF par défaut n’a aucun problème avec cette hiérarchie de classe.

La classe conteneur

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

La classe de base

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

Une des classes dérivées

 [DataContract] public class xPaymentSummary : PaymentSummary { } 

Le code de sérialisation

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

L’éxéption

System.InvalidOperationException: une erreur s’est produite lors de la génération du document XML. —> System.InvalidOperationException: le type xPaymentSummary n’était pas attendu. Utilisez l’atsortingbut XmlInclude ou SoapInclude pour spécifier les types qui ne sont pas connus de manière statique. à

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

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

Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterPaymentSummaryRequest.Write15_TRANSACTION (Object o) — Fin de la trace de la stack d’exception interne — at

System.Xml.Serialization.XmlSerializer.Serialize (espaces de noms XmlWriter xmlWriter, Object o, XmlSerializerNamespaces, Ssortingng encodingStyle, Ssortingng id) à

System.Xml.Serialization.XmlSerializer.Serialize (espaces de noms TextWriter textWriter, Object o, XmlSerializerNamespaces)
à UserQuery.RunUserAuthoredQuery () dans c: \ Utilisateurs \ Tedford \ AppData \ Local \ Temp \ uqacncyo.0.cs: ligne 47

Le problème que vous rencontrez est dû au fait que PaymentSummaryRequest définit l’espace de noms. Vous pouvez supprimer l’espace de noms ou append un espace de noms à la classe PaymentSummary :

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

Comme l’indique @Tedford dans son commentaire, l’espace de noms n’est requirejs que pour les types dérivés.

Il semble que lors de la génération de l’assembly de sérialisation XML, étant donné que le nœud racine possède un ensemble d’espace de noms et que la classe de base ne comprend pas la logique XML Include dans l’assembly de sérialisation généré.

Une autre approche pour résoudre le problème consisterait à supprimer les déclarations d’espace de noms des classes elles-mêmes et à spécifier l’espace de noms sur le constructeur XmlSerializer :

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