Condividi tramite


Utilizzo della classe XmlSerializer

Windows Communication Foundation (WCF) può usare due diverse tecnologie di serializzazione per trasformare i dati nell'applicazione in XML trasmessi tra client e servizi: DataContractSerializer e XmlSerializer.

DataContractSerializer

Per impostazione predefinita WCF usa la DataContractSerializer classe per serializzare i tipi di dati. Questo serializzatore supporta i tipi seguenti:

  • Tipi primitivi (ad esempio, numeri interi, stringhe e matrici di byte), nonché alcuni tipi speciali, ad esempio XmlElement e DateTime, considerati come primitive.

  • Tipi di contratto dati (tipi contrassegnati con l'attributo DataContractAttribute ).

  • Tipi contrassegnati con l'attributo SerializableAttribute , che includono tipi che implementano l'interfaccia ISerializable .

  • Tipi che implementano l'interfaccia IXmlSerializable .

  • Molti tipi di raccolta comuni, che includono molti tipi di raccolta generici.

Molti tipi .NET Framework rientrano nelle ultime due categorie e sono quindi serializzabili. Anche le matrici di tipi serializzabili sono serializzabili. Per un elenco completo, vedere Specifica del trasferimento dei dati nei contratti di servizio.

Il DataContractSerializer, usato insieme ai contratti di dati, è il modo consigliato per scrivere i nuovi servizi WCF. Per altre informazioni, vedere Uso dei contratti dati.

XmlSerializer

WCF supporta anche la XmlSerializer classe . La XmlSerializer classe non è univoca per WCF. È lo stesso motore di serializzazione che usano i servizi Web ASP.NET. La XmlSerializer classe supporta un set di tipi molto più ristretto rispetto alla DataContractSerializer classe , ma consente molto più controllo sul codice XML risultante e supporta molto più dello standard XSD (XML Schema Definition Language). Non richiede inoltre attributi dichiarativi sui tipi serializzabili. Per altre informazioni, vedere l'argomento Serializzazione XML nella documentazione di .NET Framework. La XmlSerializer classe non supporta i tipi di contratto dati.

Quando si usa Svcutil.exe o la funzionalità Aggiungi riferimento al servizio in Visual Studio per generare codice client per un servizio di terze parti o per accedere a uno schema di terze parti, viene selezionato automaticamente un serializzatore appropriato. Se lo schema non è compatibile con DataContractSerializer, XmlSerializer viene selezionato .

Passare a XmlSerializer

A volte, potrebbe essere necessario passare manualmente a XmlSerializer. Ciò si verifica, ad esempio, nei casi seguenti:

  • Quando si esegue la migrazione di un'applicazione dai servizi Web ASP.NET a WCF, anziché creare nuovi tipi di contratti di dati, è possibile riutilizzare i tipi esistenti compatibili con XmlSerializer.

  • Quando un controllo preciso sul codice XML visualizzato nei messaggi è importante, ma un documento WSDL (Web Services Description Language) non è disponibile, ad esempio, quando si crea un servizio con tipi che devono essere conformi a uno schema pubblicato standardizzato e non compatibile con DataContractSerializer.

  • Quando si creano servizi che seguono lo standard di codifica SOAP legacy.

In questi e altri casi, è possibile passare manualmente alla XmlSerializer classe applicando l'attributo XmlSerializerFormatAttribute al servizio, come illustrato nel codice seguente.

[ServiceContract]
[XmlSerializerFormat]
public class BankingService
{
[OperationContract]
    public void ProcessTransaction(BankingTransaction bt)
    {
        // Code not shown.
    }
}

//BankingTransaction is not a data contract class,
//but is an XmlSerializer-compatible class instead.
public class BankingTransaction
{
    [XmlAttribute]
    public string Operation;
    [XmlElement]
    public Account fromAccount;
    [XmlElement]
    public Account toAccount;
    [XmlElement]
    public int amount;
}
//Notice that the Account class must also be XmlSerializer-compatible.
<ServiceContract(), XmlSerializerFormat()> _
Public Class BankingService
    <OperationContract()> _
    Public Sub ProcessTransaction(ByVal bt As BankingTransaction)
        ' Code not shown.
    End Sub
End Class


' BankingTransaction is not a data contract class,
' but is an XmlSerializer-compatible class instead.

Public Class BankingTransaction
    <XmlAttribute()> _
    Public Operation As String
    <XmlElement()> _
    Public fromAccount As Account
    <XmlElement()> _
    Public toAccount As Account
    <XmlElement()> _
    Public amount As Integer
End Class
'Notice that the Account class must also be XmlSerializer-compatible.

Considerazioni sulla sicurezza

Annotazioni

È importante prestare attenzione quando si cambiano motori di serializzazione. Lo stesso tipo può serializzare in XML in modo diverso a seconda del serializzatore in uso. Se usi accidentalmente il serializzatore errato, potresti divulgare informazioni dal tipo che non intendi divulgare.

Ad esempio, la classe DataContractSerializer serializza solo i membri contrassegnati con l'attributo DataMemberAttribute quando si serializzano tipi di contratto dati. La XmlSerializer classe serializza qualsiasi membro pubblico. Vedere il tipo nel codice seguente.

[DataContract]
public class Customer
{
    [DataMember]
    public string firstName;
    [DataMember]
    public string lastName;
    public string creditCardNumber;
}
<DataContract()> _
Public Class Customer
    <DataMember()> _
    Public firstName As String
    <DataMember()> _
    Public lastName As String
    Public creditCardNumber As String
End Class

Se il tipo viene usato inavvertitamente in un contratto di servizio in cui è selezionata la XmlSerializer classe, il creditCardNumber membro viene serializzato, cosa probabilmente non intenzionale.

Anche se la DataContractSerializer classe è l'impostazione predefinita, è possibile selezionarla in modo esplicito per il servizio (anche se questa operazione non deve mai essere necessaria) applicando l'attributo DataContractFormatAttribute al tipo di contratto di servizio.

Il serializzatore utilizzato per il servizio è una parte integrante del contratto e non può essere modificato selezionando un'associazione diversa o modificando altre impostazioni di configurazione.

Altre importanti considerazioni sulla sicurezza si applicano alla XmlSerializer classe . Prima di tutto, è consigliabile che qualsiasi applicazione WCF che usa la XmlSerializer classe sia firmata con una chiave protetta dalla divulgazione. Questa raccomandazione si applica sia quando viene eseguito un passaggio manuale a XmlSerializer, sia quando viene eseguito un passaggio automatico (tramite Svcutil.exe, Aggiungi Riferimento al Servizio o uno strumento simile). Questo perché il XmlSerializer motore di serializzazione supporta il caricamento di assembly di serializzazione pregenerati purché siano firmati con la stessa chiave dell'applicazione. Un'applicazione non firmata non è completamente protetta dalla possibilità che un assembly dannoso corrisponda al nome previsto dell'assembly di serializzazione pregenerato inserito nella cartella dell'applicazione o nella Global Assembly Cache. Naturalmente, un utente malintenzionato deve prima ottenere l'accesso in scrittura a una delle due ubicazioni per tentare questa azione.

Un'altra minaccia che esiste ogni volta che si usa XmlSerializer è correlata all'accesso in scrittura alla cartella temporanea del sistema. Il XmlSerializer motore di serializzazione crea e usa assembly di serializzazione temporanei in questa cartella. È necessario tenere presente che qualsiasi processo con accesso in scrittura alla cartella temporanea può sovrascrivere questi assembly di serializzazione con codice dannoso.

Regole per il supporto di XmlSerializer

Non è possibile applicare direttamente attributi compatibili con XmlSerializer ai parametri di operazione del contratto o ai valori restituiti. Tuttavia, possono essere applicati ai messaggi tipizzati (parti del corpo del contratto di messaggio), come illustrato nel codice seguente.

[ServiceContract]
[XmlSerializerFormat]
public class BankingService
{
    [OperationContract]
    public void ProcessTransaction(BankingTransaction bt)
    {
        //Code not shown.
    }
}

[MessageContract]
public class BankingTransaction
{
    [MessageHeader]
    public string Operation;
    [XmlElement, MessageBodyMember]
    public Account fromAccount;
    [XmlElement, MessageBodyMember]
    public Account toAccount;
    [XmlAttribute, MessageBodyMember]
    public int amount;
}
<ServiceContract(), XmlSerializerFormat()> _
Public Class BankingService
    <OperationContract()> _
    Public Sub ProcessTransaction(ByVal bt As BankingTransaction)
        'Code not shown.
    End Sub
End Class

<MessageContract()> _
Public Class BankingTransaction
    <MessageHeader()> _
    Public Operation As String
    <XmlElement(), MessageBodyMember()> _
    Public fromAccount As Account
    <XmlElement(), MessageBodyMember()> _
    Public toAccount As Account
    <XmlAttribute(), MessageBodyMember()> _
    Public amount As Integer
End Class

Se applicato ai membri del messaggio tipizzato, questi attributi sostituiscono le proprietà in conflitto sugli attributi del messaggio tipizzato. Nel codice seguente, ad esempio, ElementName esegue l'override di Name.

    [MessageContract]
    public class BankingTransaction
    {
        [MessageHeader] public string Operation;

        //This element will be <fromAcct> and not <from>:
        [XmlElement(ElementName="fromAcct"), MessageBodyMember(Name="from")]
        public Account fromAccount;

        [XmlElement, MessageBodyMember]
        public Account toAccount;

        [XmlAttribute, MessageBodyMember]
        public int amount;
}
<MessageContract()> _
Public Class BankingTransaction
    <MessageHeader()> _
    Public Operation As String

    'This element will be <fromAcct> and not <from>:
    <XmlElement(ElementName:="fromAcct"), _
        MessageBodyMember(Name:="from")> _
    Public fromAccount As Account

    <XmlElement(), MessageBodyMember()> _
    Public toAccount As Account

    <XmlAttribute(), MessageBodyMember()> _
    Public amount As Integer
End Class

L'attributo MessageHeaderArrayAttribute non è supportato quando si usa .XmlSerializer

Annotazioni

In questo caso, XmlSerializer genera l'eccezione seguente, rilasciata prima di WCF: "Un elemento dichiarato al livello superiore di uno schema non può avere maxOccurs> 1. Specificare un elemento wrapper per 'more' usando XmlArray o XmlArrayItem invece di XmlElementAttributeo usando lo stile del parametro Wrapped".

Se si riceve un'eccezione di questo tipo, verificare se si applica questa situazione.

WCF non supporta gli SoapIncludeAttribute attributi e XmlIncludeAttribute nei contratti di messaggio e di operazione. Usare invece l'attributo KnownTypeAttribute .

Tipi che implementano l'interfaccia IXmlSerializable

I tipi che implementano l'interfaccia IXmlSerializable sono completamente supportati da DataContractSerializer. L'attributo XmlSchemaProviderAttribute deve essere sempre applicato a questi tipi per controllarne lo schema.

Avvertimento

Se si serializzano tipi polimorfici, è necessario applicare XmlSchemaProviderAttribute al tipo per assicurarsi che il tipo corretto sia serializzato.

Esistono tre varietà di tipi che implementano IXmlSerializable: tipi che rappresentano contenuto arbitrario, tipi che rappresentano un singolo elemento e tipi legacy DataSet .

  • I tipi di contenuto usano un metodo del provider di schemi specificato dall'attributo XmlSchemaProviderAttribute . Il metodo non restituisce null e la IsAny proprietà dell'attributo viene lasciata al valore predefinito di false. Si tratta dell'utilizzo più comune dei IXmlSerializable tipi.

  • I tipi di elemento vengono utilizzati quando un IXmlSerializable tipo deve controllare il proprio nome dell'elemento radice. Per contrassegnare un tipo come tipo di elemento, impostare la IsAny proprietà sull'attributo XmlSchemaProviderAttribute su true o restituire null dal metodo del provider dello schema. La presenza di un metodo del provider di schemi è facoltativa per i tipi di elemento. È possibile specificare null anziché il nome del metodo in XmlSchemaProviderAttribute. Tuttavia, se IsAny è true e viene specificato un metodo del provider di schemi, il metodo deve restituire null.

  • I tipi DataSet legacy sono tipi IXmlSerializable che non sono contrassegnati con l'attributo XmlSchemaProviderAttribute. Si basano invece sul metodo per la GetSchema generazione dello schema. Questo modello viene usato per il DataSet tipo e il set di dati tipizzato deriva una classe nelle versioni precedenti del .NET Framework, ma è ora obsoleto ed è supportato solo per motivi legacy. Non contare su questo schema e applica sempre il XmlSchemaProviderAttribute ai tuoi tipi di IXmlSerializable.

Tipi di contenuto IXmlSerializable

Quando si serializza un membro dati di un tipo che implementa IXmlSerializable ed è un tipo di contenuto come definito in precedenza, il serializzatore scrive l'elemento wrapper per il membro dati e passa il controllo al metodo WriteXml. L'implementazione WriteXml può scrivere qualsiasi xml, che include l'aggiunta di attributi all'elemento wrapper. Dopo il completamento di WriteXml, il serializzatore chiude l'elemento.

Quando si deserializza un membro dati di un tipo che implementa IXmlSerializable e è un tipo di contenuto come definito in precedenza, il deserializzatore posiziona il lettore XML sull'elemento wrapper per il membro dati e passa il controllo al ReadXml metodo . Il metodo deve leggere l'intero elemento, inclusi i tag iniziale e finale. Assicurarsi che il ReadXml codice gestisca il caso in cui l'elemento sia vuoto. Inoltre, l'implementazione ReadXml non deve basarsi sull'elemento wrapper denominato in modo specifico. Il nome che viene scelto dal serializzatore può variare.

È consentito assegnare IXmlSerializable i tipi di contenuto in modo polimorfico, ad esempio, ai membri dati di tipo Object. È inoltre consentito che le istanze del tipo siano null. Infine, è possibile usare i tipi IXmlSerializable con la preservazione dell'oggetto grafico abilitata e con il NetDataContractSerializer. Tutte queste funzionalità richiedono che il serializzatore WCF allega determinati attributi all'elemento wrapper ("nil" e "type" nello spazio dei nomi dell'istanza di XML Schema e "Id", "Ref", "Type" e "Assembly" in uno spazio dei nomi specifico di WCF).

Attributi da ignorare durante l'implementazione di ReadXml

Prima di passare il controllo al ReadXml codice, il deserializzatore esamina l'elemento XML, rileva questi attributi XML speciali e agisce su di essi. Ad esempio, se "nil" è true, un valore Null viene deserializzato e ReadXml non viene chiamato. Se viene rilevato il polimorfismo, il contenuto dell'elemento viene deserializzato come se fosse un tipo diverso. Viene chiamata l'implementazione del tipo con assegnazione polimorfica di ReadXml . In ogni caso, un'implementazione ReadXml deve ignorare questi attributi speciali perché vengono gestiti dal deserializzatore.

Considerazioni sullo schema per i tipi di contenuto IXmlSerializable

Quando si esporta lo schema e un IXmlSerializable tipo di contenuto, viene chiamato il metodo del provider dello schema. Un oggetto XmlSchemaSet viene passato al metodo del provider di schemi. Il metodo può aggiungere qualsiasi schema valido al set di schemi. Il set di schemi contiene lo schema già noto al momento dell'esportazione dello schema. Quando il metodo del provider di schemi deve aggiungere un elemento al set di schemi, deve determinare se XmlSchema un oggetto con lo spazio dei nomi appropriato esiste già nel set. In caso affermativo, il metodo del provider di schemi deve aggiungere il nuovo elemento all'oggetto esistente XmlSchema. In caso contrario, deve creare una nuova XmlSchema istanza. Questo è importante se vengono usate matrici di IXmlSerializable tipi. Ad esempio, se si dispone di un IXmlSerializable tipo esportato come tipo "A" nel namespace "B", è possibile che, nel momento in cui viene chiamato il metodo del provider di schemi, il set di schemi contenga già lo schema per "B" affinché contenga il tipo "ArrayOfA".

Oltre ad aggiungere tipi a XmlSchemaSet, il metodo del provider di schemi per i tipi di contenuto deve restituire un valore non Null. Può restituire un oggetto XmlQualifiedName che specifica il nome del tipo di schema da utilizzare per il tipo specificato IXmlSerializable . Questo nome qualificato funge anche da nome e spazio dei nomi del contratto di dati per il tipo. È consentito restituire un tipo che non esiste nel set di schemi immediatamente quando viene restituito il metodo del provider di schemi. Tuttavia, è previsto che al momento dell'esportazione di tutti i tipi correlati (il Export metodo viene chiamato per tutti i tipi rilevanti in XsdDataContractExporter e la Schemas proprietà è accessibile), il tipo esiste nel set di schemi. L'accesso alla proprietà Schemas prima che siano state effettuate tutte le chiamate pertinenti Export può comportare un XmlSchemaException. Per altre informazioni sul processo di esportazione, vedere Esportazione di schemi da classi.

Il metodo del provider di schemi può anche restituire l'oggetto XmlSchemaType da utilizzare. Il tipo può essere o meno anonimo. Se è anonimo, lo schema per il IXmlSerializable tipo viene esportato come tipo anonimo ogni volta che il IXmlSerializable tipo viene usato come membro dati. Il tipo IXmlSerializable ha ancora un nome e un namespace nel contratto dati. Viene determinato come descritto in Nomi contratto dati , ad eccezione del fatto che l'attributo DataContractAttribute non può essere usato per personalizzare il nome. Se non è anonimo, deve essere uno dei tipi in XmlSchemaSet. Questo caso equivale a restituire l'elemento XmlQualifiedName del tipo.

Inoltre, viene esportata una dichiarazione di elemento globale per il tipo . Se al tipo non è applicato l'attributo XmlRootAttribute , l'elemento ha lo stesso nome e lo stesso spazio dei nomi del contratto dati e la relativa proprietà "nillable" è true. L'unica eccezione è lo spazio dei nomi dello schema (http://www.w3.org/2001/XMLSchema): se il contratto dati del tipo si trova in questo spazio dei nomi, l'elemento globale corrispondente si trova nello spazio dei nomi vuoto perché non è consentito aggiungere nuovi elementi allo spazio dei nomi dello schema. Se al tipo è applicato l'attributo XmlRootAttribute, la dichiarazione dell'elemento globale viene esportata usando le proprietà seguenti: ElementName, Namespace e IsNullable. Le impostazioni predefinite con XmlRootAttribute applicate sono il nome del contratto dati, uno spazio dei nomi vuoto e "nillable" che è true.

Le stesse regole di dichiarazione degli elementi globali si applicano ai tipi di set di dati legacy. Si noti che non è possibile eseguire l'override XmlRootAttributeXmlSchemaSet delle dichiarazioni di elementi globali aggiunte tramite codice personalizzato, aggiunte a utilizzando il metodo del provider di schemi o tramite GetSchema per i tipi di set di dati legacy.

Tipi di elemento IXmlSerializable

IXmlSerializable I tipi di elemento hanno o la IsAny proprietà impostata su true oppure il loro metodo del provider dello schema restituisce null.

La serializzazione e la deserializzazione di un tipo di elemento sono molto simili alla serializzazione e deserializzazione di un tipo di contenuto. Esistono tuttavia alcune differenze importanti:

  • L'implementazione WriteXml dovrebbe scrivere esattamente un elemento (che può naturalmente contenere più elementi figlio). Non dovrebbe scrivere attributi al di fuori di questo singolo elemento, elementi fratelli multipli o contenuti misti. L'elemento può essere vuoto.

  • L'implementazione ReadXml non deve leggere l'elemento wrapper. Ci si aspetta di leggere l'unico elemento che WriteXml produce.

  • Quando si serializza regolarmente un tipo di elemento (ad esempio, come membro di dati in un contratto dati), il serializzatore produce un elemento wrapper prima di chiamare WriteXml, come con i tipi di contenuto. Tuttavia, quando si serializza un tipo di elemento al livello superiore, il serializzatore normalmente non produce alcun elemento wrapper attorno all'elemento che scrive, a meno che non venga specificato in modo esplicito sia un nome radice sia uno spazio dei nomi durante la costruzione del serializzatore nei costruttori WriteXml o DataContractSerializer. Per altre informazioni, vedere Serializzazione e deserializzazione.

  • Quando si serializza un tipo di elemento al livello superiore senza specificare il nome radice e lo spazio dei nomi in fase di costruzione, WriteStartObject e WriteEndObject essenzialmente non eseguono alcuna operazione e WriteObjectContent chiama WriteXml. In questa modalità, l'oggetto serializzato non può essere null e non può essere assegnato polimorficamente. Inoltre, la conservazione del grafo degli oggetti non può essere abilitata e il NetDataContractSerializer non può essere usato.

  • Quando si deserializza un tipo di elemento al livello superiore senza specificare il nome radice e lo spazio dei nomi in fase di costruzione, IsStartObject restituisce true se riesce a trovare l'inizio di qualsiasi elemento. ReadObject con il verifyObjectName parametro impostato su true si comporta nello stesso modo di IsStartObject prima di leggere effettivamente l'oggetto. ReadObject passa quindi il controllo al ReadXml metodo .

Lo schema esportato per i tipi di elemento è uguale a quello XmlElement del tipo descritto in una sezione precedente, ad eccezione del fatto che il metodo del provider di schemi può aggiungere qualsiasi schema aggiuntivo a XmlSchemaSet come con i tipi di contenuto. L'uso dell'attributo XmlRootAttribute con tipi di elemento non è consentito e le dichiarazioni di elementi globali non vengono mai generate per questi tipi.

Differenze rispetto a XmlSerializer

L'interfaccia IXmlSerializable e gli attributi XmlSchemaProviderAttribute e XmlRootAttribute sono anche riconosciuti da XmlSerializer. Tuttavia, esistono alcune differenze nel modo in cui questi vengono trattati nel modello di contratto dati. Le differenze importanti sono riepilogate nell'elenco seguente:

  • Il metodo del provider di schemi deve essere pubblico da usare in XmlSerializer, ma non deve essere pubblico da usare nel modello di contratto dati.

  • Il metodo del fornitore dello schema viene chiamato quando IsAny è true nel modello di contratto dati, ma non con XmlSerializer.

  • Quando l'attributo XmlRootAttribute non è presente per i tipi di contenuto o set di dati legacy, XmlSerializer esporta una dichiarazione di elemento globale nello spazio dei nomi vuoto. Nel modello di contratto dati lo spazio dei nomi usato è in genere lo spazio dei nomi del contratto dati come descritto in precedenza.

Tenere presente queste differenze durante la creazione di tipi usati con entrambe le tecnologie di serializzazione.

Importazione dello schema IXmlSerializable

Quando si importa uno schema generato dai IXmlSerializable tipi, esistono alcune possibilità:

  • Lo schema generato può essere uno schema di contratto dati valido, come descritto in Riferimento allo schema del contratto dati. In questo caso, lo schema può essere importato come di consueto e vengono generati tipi di contratto dati regolari.

  • Lo schema generato potrebbe non essere uno schema di contratto dati valido. Ad esempio, il metodo del provider di schemi può generare uno schema che include attributi XML non supportati nel modello del contratto dati. In questo caso, è possibile importare lo schema come tipi IXmlSerializable. Questa modalità di importazione non è attivata per impostazione predefinita, ma può essere abilitata facilmente, ad esempio con l'opzione della /importXmlTypes riga di comando allo strumento Utilità metadati ServiceModel (Svcutil.exe). Questo argomento è descritto in dettaglio nell'importazione dello schema per generare classi. Si noti che è necessario lavorare direttamente con l'XML per i tipi di istanze. È anche possibile prendere in considerazione l'uso di una tecnologia di serializzazione diversa che supporta una gamma più ampia di schemi. Vedere l'argomento relativo all'uso di XmlSerializer.

  • È possibile riutilizzare i tipi esistenti IXmlSerializable nel proxy anziché generarne di nuovi. In questo caso, la funzionalità dei tipi a cui si fa riferimento descritta nell'argomento Importazione dello schema per generare tipi può essere usata per indicare il tipo da riutilizzare. Corrisponde all'uso dell'opzione /reference su svcutil.exe, che specifica l'assembly che contiene i tipi da riutilizzare.

Comportamento legacy di XmlSerializer

In .NET Framework 4.0 e versioni precedenti, xmlSerializer ha generato assembly di serializzazione temporanei scrivendo codice C# in un file. Il file è stato quindi compilato in un assembly. Questo comportamento ha avuto alcune conseguenze indesiderate, ad esempio rallentare il tempo di avvio per il serializzatore. In .NET Framework 4.5 questo comportamento è stato modificato per generare gli assembly senza richiedere l'uso del compilatore. Alcuni sviluppatori potrebbero voler visualizzare il codice C# generato. È possibile specificare di usare questo comportamento legacy tramite la configurazione seguente:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.xml.serialization>
    <xmlSerializer tempFilesLocation='e:\temp\XmlSerializerBug' useLegacySerializerGeneration="true" />
  </system.xml.serialization>
  <system.diagnostics>
    <switches>
      <add name="XmlSerialization.Compilation" value="1" />
    </switches>
  </system.diagnostics>
</configuration>

Se si verificano problemi di compatibilità, ad esempio la serializzazione mancata di una classe derivata con un override non pubblico nuovo, è possibile tornare al comportamento legacy usando la configurazione seguente.

<configuration>
  <appSettings>
    <add key="System:Xml:Serialization:UseLegacySerializerGeneration" value="true" />
  </appSettings>
</configuration>

In alternativa alla configurazione precedente, è possibile usare la configurazione seguente in un computer che esegue .NET Framework 4.5 o versione successiva:

<configuration>
  <system.xml.serialization>
    <xmlSerializer useLegacySerializerGeneration="true"/>
  </system.xml.serialization>
</configuration>

Annotazioni

L'opzione <xmlSerializer useLegacySerializerGeneration="true"/> funziona solo in un computer che esegue .NET Framework 4.5 o versione successiva. L'approccio precedente appSettings funziona su tutte le versioni di .NET Framework.

Vedere anche