XmlSerializer - Si è verificato un errore nel tipo di riflessione


332

Usando C # .NET 2.0, ho una classe di dati compositi che ha l' [Serializable]attributo su di essa. Sto creando una XMLSerializerclasse e la passo nel costruttore:

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

Ricevo un'eccezione che dice:

Si è verificato un errore nel riflettere il tipo.

All'interno della classe di dati c'è un altro oggetto composito. Anche questo deve avere l' [Serializable]attributo o, disponendolo sull'oggetto superiore, lo applica in modo ricorsivo a tutti gli oggetti all'interno?

Risposte:


413

Guarda l'eccezione interiore che stai ricevendo. Ti dirà quale campo / proprietà ha problemi a serializzare.

È possibile escludere campi / proprietà dalla serializzazione xml decorandoli con l' [XmlIgnore]attributo.

XmlSerializernon usa l' [Serializable]attributo, quindi dubito che sia questo il problema.


11
Il mio oggetto aveva un campo Uri, che ha causato questa eccezione; la classe Uri non ha un costruttore senza parametri. Grazie per il consiglio.
ford,

10
Mi sono imbattuto in questo con una ricerca su Google - il mio problema particolare era avere una proprietà nella mia classe "da serializzare" come IListquando doveva essere List.
Paul Aldred-Bann,

7
Come si osserva una "eccezione interiore"?
David,

7
o aggiungi "@exception" a un orologio
arolson101

19
Grazie, questa risposta mi ha aiutato. Inizialmente ho esaminato l'eccezione interna e ho appena visto la menzione della classe principale. Ma mi sono reso conto che avrei potuto approfondire le innerexceptions delle innrexceptions e, alla fine, 5 livelli più in basso, ho trovato il problema. Avevo lezioni contrastanti. Grazie.
Louis van Tonder,

111

Ricorda che le classi serializzate devono avere costruttori predefiniti (cioè senza parametri). Se non hai nessun costruttore, va bene; ma se hai un costruttore con un parametro, dovrai aggiungere anche quello predefinito.


4
Grazie del promemoria! Odio che questo è un errore di runtime con poche spiegazioni.
Jared Updike,

Continuo a ripetere questo errore ancora e ancora. grazie per avermi ricordato di usare un costruttore senza parametri ^^
aZtraL-EnForceR

25

Ho avuto un problema simile e si è scoperto che il serializzatore non era in grado di distinguere tra 2 classi che avevo con lo stesso nome (una era una sottoclasse dell'altra). L'eccezione interiore appariva così:

'Tipi BaseNamespace.Class1' e 'BaseNamespace.SubNamespace.Class1' utilizzano entrambi il nome del tipo XML, 'Class1', dallo spazio dei nomi ''. Utilizzare gli attributi XML per specificare un nome XML e / o uno spazio dei nomi univoci per il tipo.

Dove BaseNamespace.SubNamespace.Class1 è una sottoclasse di BaseNamespace.Class1.

Quello che dovevo fare era aggiungere un attributo a una delle classi (ho aggiunto alla classe base):

[XmlType("BaseNamespace.Class1")]

Nota: se hai più livelli di classi, devi aggiungere anche un attributo.


Questo risolto il problema per me, grazie, +1; Avevo un'impostazione simile con diversi oggetti Processor *, ognuno con una classe interna Config. Il runtime non è stato in grado di distinguere tra SomeNS.Processor1.Config e SomeNS.Processor2.Config.
damix911,


6

I motivi più comuni da me:

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


5

Se è necessario gestire attributi specifici (ad esempio Dizionario o qualsiasi classe), è possibile implementare l' interfaccia IXmlSerialiable , che consentirà una maggiore libertà a costo di una codifica più dettagliata .

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
}

C'è un articolo interessante , che mostra un modo elegante per implementare un modo sofisticato per "estendere" XmlSerializer.


L'articolo dice:

IXmlSerializable è coperto dalla documentazione ufficiale, ma la documentazione afferma che non è destinata all'uso pubblico e non fornisce alcuna informazione oltre a ciò. Ciò indica che il team di sviluppo voleva riservarsi il diritto di modificare, disabilitare o addirittura rimuovere completamente questo hook di estensibilità lungo la strada. Tuttavia, fintanto che sei disposto ad accettare questa incertezza e ad affrontare possibili cambiamenti in futuro, non c'è motivo di non poterne trarre vantaggio.

Perché questo, suggerisco di implementare le tue IXmlSerializableclassi, al fine di evitare implementazioni troppo complicate.

... potrebbe essere semplice implementare la nostra XmlSerializerclasse personalizzata usando la riflessione.


4

Ho scoperto che la classe del dizionario in .Net 2.0 non è serializzabile tramite XML, ma serializza bene quando si utilizza la serializzazione binaria.

Ho trovato un lavoro da queste parti .


3

Recentemente ho ottenuto questo in una classe parziale di riferimento web quando si aggiunge una nuova proprietà. La classe generata automaticamente stava aggiungendo i seguenti attributi.

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

Avevo bisogno di aggiungere un attributo simile con un ordine superiore all'ultimo nella sequenza generata automaticamente e questo mi ha risolto il problema.


3

Ho appena ricevuto lo stesso errore e ho scoperto che IEnumerable<SomeClass>il problema era una proprietà di tipo . Sembra che IEnumerablenon possa essere serializzato direttamente.

Invece, si potrebbe usare List<SomeClass>.


2

Anch'io pensavo che l'attributo Serializable dovesse essere sull'oggetto, ma a meno che io non sia un noob completo (sono nel mezzo di una sessione di codifica a tarda notte) i seguenti lavori dello 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();
        }
    }

}

Immagino che XmlSerializer stia usando la riflessione sulle proprietà pubbliche.


1

Ho avuto una situazione in cui l'Ordine era lo stesso per due elementi di seguito

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

.... un po 'di codice ...

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

Quando ho modificato il codice per incrementare l'ordine di uno per ogni nuova proprietà nella classe, l'errore è scomparso.


1

Stavo ottenendo lo stesso errore quando ho creato una proprietà con un tipo di dati - Type. Su questo, stavo ricevendo un errore - Si è verificato un errore che riflette il tipo. Ho continuato a controllare l '"InnerException" di ogni eccezione dal dock di debug e ho ottenuto il nome del campo specifico (che era Type) nel mio caso. La soluzione è la seguente:

    [XmlIgnore]
    public Type Type { get; set; }

0

Si noti inoltre che non è possibile serializzare i controlli dell'interfaccia utente e che qualsiasi oggetto che si desidera trasferire negli Appunti deve essere serializzabile, altrimenti non può essere trasferito ad altri processi.



0

Ho avuto lo stesso problema e nel mio caso l'oggetto aveva un ReadOnlyCollection. Una raccolta deve implementare il metodo Aggiungi per essere serializzabile.


Questa non è una risposta adeguata alla domanda. Ci sono altre 15 risposte già su questa domanda. Se ritieni che la tua risposta sia migliore delle altre, dovresti fornire maggiori dettagli a riguardo. Fornire alcuni frammenti di codice e di output aiuta sempre gli utenti. Prima di postare le vostre risposte considerare la lettura -> stackoverflow.com/help/how-to-answer
Amit Phaltankar

0

Ho una soluzione leggermente diversa da quella descritta qui finora, quindi per ogni civiltà futura ecco la mia!

Avevo dichiarato un tipo di dati di "tempo" in quanto il tipo originale era un TimeSpane successivamente modificato in un String:

[System.Xml.Serialization.XmlElementAttribute(DataType="time", Order=3)]

tuttavia il tipo effettivo era una stringa

public string TimeProperty {
    get {
        return this.timePropertyField;
    }
    set {
        this.timePropertyField = value;
        this.RaisePropertyChanged("TimeProperty");
    }
}

rimuovendo la DateTypeproprietà è Xmlpossibile serializzare

[System.Xml.Serialization.XmlElementAttribute(Order=3)]
public string TimeProperty {
    get {
        return this.timePropertyField;
    }
    set {
        this.timePropertyField = value;
        this.RaisePropertyChanged("TimeProperty");
    }
}

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

O

[XmlIgnore]
string [] strFielsName {get;set;}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.