XmlSerializer - il y avait une erreur reflétant le type

en utilisant C# .NET 2.0, j'ai une classe de données composite qui a l'attribut [Serializable] dessus. Je crée une classe XMLSerializer et je la passe au constructeur:

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

je reçois une exception disant:

il y avait une erreur de type.

dans la classe de données, il y a un autre objet composite. Est-ce que cela doit également avoir le [Serializable] attribut, ou en l'ayant sur l'objet supérieur, est-ce qu'il l'applique récursivement à tous les objets à l'intérieur?

310
demandé sur Ryan Kohn 2008-09-13 18:40:21

16 réponses

regardez l'exception intérieure que vous obtenez. Il vous indiquera quel champ / propriété il a des problèmes de sérialisation.

vous pouvez exclure des Champs/propriétés de la sérialisation xml en les décorant avec l'attribut [XmlIgnore] .

Je ne pense pas que XmlSerializer utilise l'attribut [Serializable] , donc je doute que ce soit le problème.

389
répondu Lamar 2014-12-11 08:06:59

se rappeler que les classes sérialisées doivent avoir des constructeurs par défaut (c.-à-d. sans paramètres). Si vous n'avez pas de constructeur, c'est bien; mais si vous avez un constructeur avec un paramètre, vous devez ajouter la valeur par défaut de trop.

107
répondu Jeremy McGee 2008-09-13 16:23:20

j'ai eu un problème similaire, et il s'est avéré que le sérialiseur ne pouvait pas distinguer entre 2 classes que j'avais avec le même nom (un était une sous-classe de l'autre). L'exception intérieure ressemblait à ceci:

'Types BaseNamespace.Classe1 ' et ' BaseNamespace.SubNamespace.Class1 'les deux utilisent le nom de type XML, 'Class1', de namespace ". Utilisez les attributs XML pour spécifier un nom XML unique et/ou un espace de nom pour le type.

où BaseNamespace.SubNamespace.Classe1 est une sous-classe de BaseNamespace.Class1.

Ce que je devais faire était d'ajouter un attribut à l'une des classes (j'ai ajouté à la classe de base):

[XmlType("BaseNamespace.Class1")]

Note: Si vous avez plus de couches de classes, vous devez y ajouter un attribut.

21
répondu Dennis Calla 2011-09-16 21:51:10

sachez aussi que XmlSerializer ne peut pas sérialiser les propriétés abstraites.. Voir ma question ici (à laquelle j'ai ajouté le code de la solution)..

Sérialisation XML et a Hérité de Types

7
répondu Rob Cooper 2017-05-23 12:34:51

les raisons les Plus communes par moi:

 - the object being serialized has no parameterless constructor
 - the object contains Dictionary
 - the object has some public Interface members
6
répondu Stefan Michev 2014-02-22 12:43:26

Tous les objets dans le graphe de sérialisation doivent être sérialisables.

puisque XMLSerializer est une boîte noire, vérifiez ces liens si vous voulez déboguer plus loin dans le processus de sérialisation..

changement d'emplacement des sorties XmlSerializer assemblages temporaires

comment déboguer dans un assemblage généré par XmlSerializer

5
répondu Gulzar Nazim 2015-05-05 14:34:06

si vous avez besoin de gérer des attributs spécifiques (i.e. dictionnaire, ou n'importe quelle classe), vous pouvez mettre en œuvre le ixmlserialable interface, qui vous permettra plus de liberté au coût de plus verbeux codage .

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
}

il y a un intéressant article , qui montrent une façon élégante d'implémenter une façon sophistiquée pour" étendre " le XmlSerializer.


l'article dit:

Ixmlserialisable est couvert dans la documentation officielle, mais la documentation indique qu'il n'est pas destiné à l'usage public et ne fournit aucune information au-delà de cela. Cela indique que l'équipe de développement a voulu se réserver le droit de modifier, désactiver, ou même supprimer complètement ce crochet d'extensibilité sur la route. Cependant, tant que vous êtes prêt à accepter cette incertitude et à faire face à d'éventuels changements à l'avenir, il n'y a pas de raison que ce soit, vous ne pouvez pas en profiter.

parce que ceci, je suggère d'implémenter vos propres classes IXmlSerializable , afin d'éviter des implémentations trop compliquées.

... il pourrait être simple de mettre en œuvre notre classe personnalisée XmlSerializer en utilisant la réflexion.

5
répondu Luca 2017-04-01 08:02:09

j'ai découvert que la classe de dictionnaire dans .Net 2.0 n'est pas sérialisable en utilisant XML, mais sérialise bien lorsque la sérialisation binaire est utilisée.

j'ai trouvé un travail autour de ici .

4
répondu Charlie Salts 2009-07-02 19:32:19

j'ai récemment obtenu ceci dans une classe partielle de référence web lors de l'ajout d'une nouvelle propriété. La classe générée automatiquement ajoutait les attributs suivants.

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

j'avais besoin d'ajouter un attribut similaire avec un ordre supérieur au dernier dans la séquence générée automatiquement et cela l'a corrigé pour moi.

3
répondu LepardUK 2010-12-17 14:15:18

moi aussi j'ai pensé que l'attribut Serialisable devait être sur l'objet mais à moins d'être un noob complet (je suis au milieu d'une session de codage tard la nuit) les travaux suivants du 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();
        }
    }

}

j'imagine que le XmlSerializer utilise la réflexion sur les propriétés publiques.

2
répondu Darren 2008-09-13 15:23:04

j'ai eu une situation où l'Ordre était le même pour les deux éléments dans une rangée

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

.... un peu de code ...

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

lorsque j'ai changé le code pour augmenter l'ordre d'un pour chaque nouvelle propriété dans la classe, l'erreur a disparu.

1
répondu Jeremy Brown 2014-09-10 10:57:44

j'ai juste eu la même erreur et j'ai découvert qu'une propriété de type IEnumerable<SomeClass> était le problème. Il semble que IEnumerable ne puisse pas être sérialisé directement.

1
répondu jkokorian 2015-05-05 14:35:25

notez également que vous ne pouvez pas sérialiser les contrôles de l'interface utilisateur et que tout objet que vous voulez transmettre sur le presse-papiers doit être sérialisable sinon il ne peut pas être transmis à d'autres processus.

0
répondu Phil Wright 2008-09-13 14:55:17

j'ai utilisé la classe NetDataSerialiser pour sérialiser mes cours de domaine. NetDataContractSerializer Class .

les classes de domaines sont partagées entre le client et le serveur.

0
répondu Peter Mortensen 2010-03-22 12:27:07

[System.XML.Sérialisation.XmlElementAttribute ("strFieldName", Form = System.XML.Schéma.XmlSchemaForm.Non qualifié)]

//Ou

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

0
répondu Kiran.Bakwad 2017-02-16 11:48:17

j'ai eu le même problème et dans mon cas, l'objet avait une ReadOnlyCollection. Une collection doit implémenter la méthode Add pour être sérialisable.

0
répondu Curious Dev 2017-05-26 01:19:58