Domanda

Utilizzando C# .NET 2.0, ho una classe di dati composita che ha il file [Serializable] attribuire su di esso.Sto creando un XMLSerializer class e passandolo al costruttore:

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

Ricevo un'eccezione che dice:

Si è verificato un errore durante la riflessione del tipo.

All'interno della classe dati c'è un altro oggetto composito.Anche questo deve avere il file [Serializable] o avendolo sull'oggetto in alto, lo applica ricorsivamente a tutti gli oggetti all'interno?

È stato utile?

Soluzione

Guarda l'eccezione interiore che stai ottenendo.Ti dirà quale campo/proprietà ha problemi di serializzazione.

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

Non lo penso XmlSerializer utilizza il [Serializable] attributo, quindi dubito che sia questo il problema.

Altri suggerimenti

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

Ho avuto un problema simile e si è scoperto che il serializzatore non riusciva a distinguere tra 2 classi che avevo con lo stesso nome (una era una sottoclasse dell'altra).L'eccezione interna assomigliava a questa:

Entrambi i tipi "BaseNamespace.Class1" e "BaseNamespace.SubNamespace.Class1" utilizzano 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 (l'ho aggiunto alla classe base):

[XmlType("BaseNamespace.Class1")]

Nota:Se hai più livelli di classi devi aggiungere un attributo anche a loro.

Tieni presente anche questo XmlSerializer non è possibile serializzare proprietà astratte..Vedi la mia domanda Qui (a cui ho aggiunto il codice della soluzione).

Serializzazione XML e tipi ereditati

Motivi più comuni da me:

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

Tutti gli oggetti nel grafico di serializzazione devono essere serializzabili.

Da XMLSerializer è una scatola nera, controlla questi collegamenti se desideri eseguire ulteriormente il debug del processo di serializzazione.

Modifica del punto in cui XmlSerializer restituisce gli assembly temporanei

COME:Eseguire il debug in un assembly generato da .NET XmlSerializer

Se è necessario gestire attributi specifici (ad es.Dizionario o qualsiasi classe), puoi implementare il file IXmlSerializzabile interfaccia, che ti consentirà maggiore libertà al 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 interessante articolo, che mostrano un modo elegante per implementare un modo sofisticato per "estendere" XmlSerializer.


L'articolo dice:

IXmlSerializable è trattato nella documentazione ufficiale, ma la documentazione afferma che non è destinato all'uso pubblico e non fornisce informazioni oltre a ciò.Ciò indica che il team di sviluppo voleva riservarsi il diritto di modificare, disabilitare o addirittura rimuovere completamente questo gancio di estensibilità in futuro.Tuttavia, finché sei disposto ad accettare questa incertezza e ad affrontare possibili cambiamenti in futuro, non c'è motivo per cui non puoi trarne vantaggio.

Per questo motivo, suggerisco di implementare il tuo IXmlSerializable classi, per evitare implementazioni troppo complicate.

...potrebbe essere semplice implementare la nostra abitudine XmlSerializer classe utilizzando la riflessione.

Ho scoperto che la classe Dictionary in .Net 2.0 non è serializzabile utilizzando XML, ma serializza bene quando viene utilizzata la serializzazione binaria.

Ho trovato una soluzione Qui.

Recentemente l'ho ottenuto in una classe parziale di riferimento web quando ho aggiunto una nuova proprietà.La classe generata automaticamente aggiungeva 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 ha risolto il problema.

Anch'io pensavo che l'attributo Serializable dovesse essere sull'oggetto ma, a meno che non sia un totale noob (sono nel bel mezzo di una sessione di codifica a tarda notte), i seguenti lavori dal 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 utilizzi la riflessione sulle proprietà pubbliche.

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

Invece, si potrebbe usare List<SomeClass>.

Ho avuto una situazione in cui l'ordine era lo stesso per due elementi di fila

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

....qualche 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.

Tieni inoltre presente che non puoi serializzare i controlli dell'interfaccia utente e che qualsiasi oggetto che desideri passare negli appunti deve essere serializzabile altrimenti non può essere passato ad altri processi.

Ho usato il NetDataSerialiser Classe per serializzare le mie lezioni di dominio. Classe NetDataContractSerializer.

Le classi di dominio sono condivise tra client e server.

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

//O

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

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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top