Question

En utilisant C# .NET 2.0, j'ai une classe de données composite qui a le [Serializable] attribut dessus.je crée un XMLSerializer classe et en passant cela au constructeur :

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

Je reçois une exception disant:

Une erreur s'est produite lors de la réflexion du type.

À l’intérieur de la classe de données se trouve un autre objet composite.Est-ce que cela doit également avoir le [Serializable] attribut, ou en l'ayant sur l'objet supérieur, l'applique-t-il de manière récursive à tous les objets à l'intérieur ?

Était-ce utile?

La solution

Regardez l'exception interne que vous obtenez.Il vous dira quel champ/propriété il a du mal à sérialiser.

Vous pouvez exclure des champs/propriétés de la sérialisation XML en les décorant avec le [XmlIgnore] attribut.

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

Autres conseils

N'oubliez pas que les classes sérialisées doivent avoir une valeur par défaut (c'est-à-direconstructeurs sans paramètre).Si vous n'avez aucun constructeur, ce n'est pas un problème ;mais si vous avez un constructeur avec un paramètre, vous devrez également ajouter celui par défaut.

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

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

Où BaseNamespace.SubNamespace.Class1 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 plusieurs couches de classes, vous devez également leur ajouter un attribut.

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

Sérialisation XML et types hérités

Raisons les plus courantes selon moi :

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

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

Depuis XMLSerializer est une boîte noire, vérifiez ces liens si vous souhaitez poursuivre le débogage dans le processus de sérialisation.

Modification de l'endroit où XmlSerializer génère des assemblys temporaires

COMMENT:Déboguer dans un assembly généré par .NET XmlSerializer

Si vous devez gérer des attributs spécifiques (par ex.Dictionnaire, ou n'importe quelle classe), vous pouvez implémenter le IXmlSerialiable interface, qui vous permettra plus de liberté au prix d'un codage plus verbeux.

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 montre une manière élégante d'implémenter une manière sophistiquée d'"étendre" le XmlSerializer.


L'article dit :

IXmlSerialised est couvert dans la documentation officielle, mais la documentation indique qu'elle n'est pas destinée à un usage public et ne fournit aucune information au-delà.Cela indique que l'équipe de développement souhaitait se réserver le droit de modifier, de désactiver ou même de supprimer complètement ce hook d'extensibilité ultérieurement.Cependant, tant que vous êtes prêt à accepter cette incertitude et à faire face à d’éventuels changements à l’avenir, il n’y a aucune raison pour que vous ne puissiez pas en profiter.

Parce que cela, je suggère de mettre en œuvre votre propre IXmlSerializable classes, afin d'éviter des implémentations trop compliquées.

...il pourrait être simple d'implémenter notre coutume XmlSerializer cours utilisant la réflexion.

J'ai découvert que la classe Dictionary dans .Net 2.0 n'est pas sérialisable à l'aide de XML, mais se sérialise bien lorsque la sérialisation binaire est utilisée.

J'ai trouvé un travail ici.

J'ai récemment obtenu cela 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 a résolu le problème pour moi.

Moi aussi, je pensais que l'attribut Serialisable devait être sur l'objet, mais à moins que je ne sois un novice complet (je suis au milieu d'une session de codage de fin de soirée), les travaux suivants du Compilateur d'extraits:

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 XmlSerializer utilise la réflexion sur les propriétés publiques.

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

Au lieu de cela, on pourrait utiliser List<SomeClass>.

J'ai eu une situation où l'ordre était le même pour deux éléments d'affilée

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

....du code...

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

Lorsque j'ai modifié le code pour incrémenter l'ordre de un pour chaque nouvelle propriété de la classe, l'erreur a disparu.

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

J'ai utilisé le NetDataSerialiser classe pour sérialiser mes classes de domaine. Classe NetDataContractSerializer.

Les classes de domaine sont partagées entre le client et le serveur.

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

//Ou

Xmlignore] String [] strfielsname {get; set;}

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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top