Partager via


Utilisation de la classe XmlSerializer

Windows Communication Foundation (WCF) peut utiliser deux technologies de sérialisation différentes pour transformer les données de votre application en XML transmises entre les clients et les services : DataContractSerializer et XmlSerializer.

DataContractSerializer

Par défaut, WCF utilise la DataContractSerializer classe pour sérialiser les types de données. Ce sérialiseur prend en charge les types suivants :

  • Types primitifs (par exemple, entiers, chaînes et tableaux d’octets), ainsi que certains types spéciaux, tels que XmlElement et DateTime, qui sont traités comme des primitives.

  • Types de contrat de données (types marqués avec l’attribut DataContractAttribute ).

  • Types marqués avec l’attribut SerializableAttribute , qui incluent les types qui implémentent l’interface ISerializable .

  • Types qui implémentent l’interface IXmlSerializable .

  • De nombreux types de collection courants, qui incluent de nombreux types de collection génériques.

De nombreux types .NET Framework appartiennent aux deux dernières catégories et sont donc sérialisables. Les tableaux de types sérialisables sont également sérialisables. Pour obtenir une liste complète, consultez Spécification du transfert de données dans les contrats de service.

Le DataContractSerializer, utilisé avec les types de contrats de données, est la méthode recommandée pour écrire de nouveaux services WCF. Pour plus d’informations, consultez Utilisation des contrats de données.

XmlSerializer

WCF prend également en charge la XmlSerializer classe. La XmlSerializer classe n’est pas unique à WCF. Il s’agit du même moteur de sérialisation que les services Web ASP.NET utilisent. La XmlSerializer classe prend en charge un ensemble de types beaucoup plus étroit que la DataContractSerializer classe, mais permet beaucoup plus de contrôle sur le code XML résultant et prend en charge beaucoup plus de la norme XSD (XML Schema Definition Language). Il ne nécessite pas non plus d’attributs déclaratifs sur les types sérialisables. Pour plus d’informations, consultez la rubrique sérialisation XML dans la documentation .NET Framework. La XmlSerializer classe ne prend pas en charge les types de contrats de données.

Lorsque vous utilisez Svcutil.exe ou la fonctionnalité Ajouter une référence de service dans Visual Studio pour générer du code client pour un service tiers ou pour accéder à un schéma tiers, un sérialiseur approprié est automatiquement sélectionné pour vous. Si le schéma n’est pas compatible avec le DataContractSerializer, le XmlSerializer est sélectionné.

Basculer vers XmlSerializer

Parfois, vous devrez peut-être passer manuellement à XmlSerializer. Cela se produit, par exemple, dans les cas suivants :

  • Lors de la migration d’une application à partir de ASP.NET services Web vers WCF, vous pouvez réutiliser des types existants compatibles, XmlSerializerau lieu de créer de nouveaux types de contrat de données.

  • Lorsque le contrôle précis sur le code XML qui apparaît dans les messages est important, mais qu’un document WSDL (Web Services Description Language) n’est pas disponible, par exemple lors de la création d’un service avec des types qui doivent se conformer à un schéma standardisé et publié qui n’est pas compatible avec le DataContractSerializer.

  • Lors de la création de services qui suivent la norme d’encodage SOAP héritée.

Dans ces cas et dans d’autres cas, vous pouvez basculer manuellement vers la XmlSerializer classe en appliquant l’attribut XmlSerializerFormatAttribute à votre service, comme indiqué dans le code suivant.

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

Considérations relatives à la sécurité

Remarque

Il est important de faire attention lors du changement de moteurs de sérialisation. Le même type peut sérialiser au format XML différemment en fonction du sérialiseur utilisé. Si vous utilisez accidentellement le mauvais sérialiseur, vous pourriez divulguer des informations du type que vous n’avez pas l’intention de divulguer.

Par exemple, la classe DataContractSerializer sérialise uniquement les membres marqués par l’attribut DataMemberAttribute lorsqu'elle sérialise des types de contrat de données. La XmlSerializer classe sérialise tout membre public. Consultez le type dans le code suivant.

[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

Si le type est utilisé par inadvertance dans un contrat de service où la classe XmlSerializer est sélectionnée, l'élément creditCardNumber est sérialisé, ce qui n'est probablement pas prévu.

Même si la DataContractSerializer classe est la valeur par défaut, vous pouvez la sélectionner explicitement pour votre service (bien que cela ne soit jamais obligatoire) en appliquant l’attribut DataContractFormatAttribute au type de contrat de service.

Le sérialiseur utilisé pour le service fait partie intégrante du contrat et ne peut pas être modifié en sélectionnant une autre liaison ou en modifiant d’autres paramètres de configuration.

D’autres considérations importantes relatives à la sécurité s’appliquent à la XmlSerializer classe. Tout d’abord, il est fortement recommandé que toute application WCF qui utilise la XmlSerializer classe soit signée avec une clé protégée contre la divulgation. Cette recommandation s'applique à la fois lorsqu'un passage manuel ou automatique via XmlSerializer est effectué (par Svcutil.exe, Ajouter une référence de service ou un outil similaire). Cela est dû au fait que le XmlSerializer moteur de sérialisation prend en charge le chargement d’assemblys de sérialisation prégénés tant qu’ils sont signés avec la même clé que l’application. Une application non signée est complètement vulnérable face à la possibilité qu’un assembly malveillant, correspondant au nom attendu de l’assembly de sérialisation prégénéré, soit placé dans le dossier de l’application ou dans le Global Assembly Cache. Bien sûr, un attaquant doit d’abord obtenir l’accès en écriture à l’un de ces deux emplacements pour tenter cette action.

Une autre menace qui existe chaque fois que vous utilisez XmlSerializer est liée à l’accès en écriture au dossier temporaire système. Le moteur de sérialisation XmlSerializer crée et utilise des assemblys de sérialisation temporaires dans ce dossier. Sachez que tout processus disposant d’un accès en écriture au dossier temporaire peut remplacer ces assemblys de sérialisation avec du code malveillant.

Règles pour la prise en charge de XmlSerializer

Vous ne pouvez pas directement appliquer des attributs compatibles XmlSerializer aux paramètres d'opération de contrat ou aux valeurs de retour. Toutefois, ils peuvent être appliqués aux messages typés (parties du corps du contrat de message), comme indiqué dans le code suivant.

[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

Lorsqu’ils sont appliqués aux membres de message typés, ces attributs remplacent les propriétés qui entrent en conflit sur les attributs de message typés. Par exemple, dans le code suivant, ElementName remplace 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’attribut MessageHeaderArrayAttribute n’est pas pris en charge lors de l’utilisation du XmlSerializer.

Remarque

Dans ce cas, l’exception suivante est lancée par XmlSerializer, et elle est gérée avant WCF : « Un élément déclaré au niveau supérieur d’un schéma ne peut pas être de type maxOccurs> 1. Fournissez un élément wrapper pour « more » en utilisant XmlArray ou XmlArrayItem à la place de XmlElementAttribute ou en utilisant le style de paramètre Wrapped. ».

Si vous recevez une telle exception, vérifiez si cette situation s’applique.

WCF ne prend pas en charge les attributs SoapIncludeAttribute et XmlIncludeAttribute dans les contrats de message et les contrats d’opération. Utilisez plutôt l’attribut KnownTypeAttribute.

Types qui implémentent l’interface IXmlSerializable

Les types qui implémentent l’interface IXmlSerializable sont entièrement pris en charge par le DataContractSerializer. L’attribut XmlSchemaProviderAttribute doit toujours être appliqué à ces types pour contrôler leur schéma.

Avertissement

Si vous sérialisez des types polymorphes, vous devez appliquer le XmlSchemaProviderAttribute au type afin de vous assurer que le type correct est sérialisé.

Il existe trois variétés de types qui implémentent IXmlSerializable: les types qui représentent du contenu arbitraire, des types qui représentent un élément unique et des types hérités DataSet .

  • Les types de contenu utilisent une méthode de fournisseur de schéma spécifiée par l’attribut XmlSchemaProviderAttribute . La méthode ne retourne null pas et la IsAny propriété de l’attribut est laissée à sa valeur falsepar défaut . Il s’agit de l’utilisation la plus courante des IXmlSerializable types.

  • Les types d’éléments sont utilisés lorsqu’un IXmlSerializable type doit contrôler son propre nom d’élément racine. Pour marquer un type comme type élément, affectez à la propriété IsAny sur l'attribut XmlSchemaProviderAttribute la valeur true ou retournez null à partir de la méthode du fournisseur de schéma. L’utilisation d’une méthode de fournisseur de schéma est facultative pour les types d’éléments : vous pouvez spécifier null au lieu du nom de la méthode dans le XmlSchemaProviderAttribute. Toutefois, si IsAny est true et qu'une méthode de fournisseur de schéma est spécifiée, la méthode doit retourner null.

  • Les types DataSet hérités sont des types IXmlSerializable qui ne sont pas marqués avec l’attribut XmlSchemaProviderAttribute. Au lieu de cela, ils s’appuient sur la GetSchema méthode de génération de schéma. Ce modèle est utilisé pour le type DataSet et son ensemble de données typé dérive d'une classe dans les versions antérieures du .NET Framework, mais il est maintenant obsolète et n'est pris en charge que pour des raisons de compatibilité. Ne vous fiez pas à ce modèle et appliquez toujours XmlSchemaProviderAttribute à vos types IXmlSerializable.

Types de contenu IXmlSerializable

Lors de la sérialisation d’un membre de données d’un type qui implémente IXmlSerializable et est un type de contenu tel que défini précédemment, le sérialiseur écrit l’élément wrapper pour le membre de données et passe le contrôle à la WriteXml méthode. L’implémentation WriteXml peut écrire n’importe quel code XML, qui inclut l’ajout d’attributs à l’élément wrapper. Une fois WriteXml terminé, le sérialiseur ferme l’élément.

Lors de la désérialisation d’un membre de données d’un type qui implémente IXmlSerializable et est un type de contenu tel que défini précédemment, le désérialiseur positionne le lecteur XML sur l’élément wrapper pour le membre de données et passe le contrôle à la ReadXml méthode. La méthode doit lire l’ensemble de l’élément, y compris les balises de début et de fin. Assurez-vous que votre ReadXml code gère le cas où l’élément est vide. En outre, votre ReadXml implémentation ne doit pas s’appuyer sur l’élément wrapper nommé d’une manière particulière. Le nom choisi par le sérialiseur peut varier.

Il est autorisé à affecter IXmlSerializable des types de contenu polymorphes, par exemple aux membres de données de type Object. Il est également permis que les instances de type soient nulles. Enfin, il est possible d'utiliser des types IXmlSerializable avec la conservation des graphiques d'objet activée et avec NetDataContractSerializer. Toutes ces fonctionnalités nécessitent que le sérialiseur WCF attache certains attributs à l’élément wrapper (« nil » et « type » dans l’espace de noms d’instance de schéma XML et « Id », « Ref », « Type » et « Assembly » dans un espace de noms spécifique à WCF).

Attributs à ignorer lors de l’implémentation de ReadXml

Avant de passer le contrôle à votre ReadXml code, le désérialiseur examine l’élément XML, détecte ces attributs XML spéciaux et agit dessus. Par exemple, si « nil » est true, une valeur null est désérialisée et ReadXml n’est pas appelée. Si le polymorphisme est détecté, le contenu de l’élément est désérialisé comme s’il s’agissait d’un type différent. L'implémentation de ReadXml du type assigné de manière polymorphe est appelée. Dans tous les cas, une ReadXml implémentation doit ignorer ces attributs spéciaux, car ils sont gérés par le désérialiseur.

Considérations sur le schéma pour les types de contenu IXmlSerializable

Lors de l’exportation du schéma et d’un type de IXmlSerializable contenu, la méthode du fournisseur de schémas est appelée. Un XmlSchemaSet est passé à la méthode du fournisseur de schéma. La méthode peut ajouter n’importe quel schéma valide au jeu de schémas. Le jeu de schémas contient le schéma déjà connu au moment où l’exportation de schéma se produit. Lorsque la méthode du fournisseur de schémas doit ajouter un élément au jeu de schémas, elle doit déterminer si un XmlSchema espace de noms approprié existe déjà dans l’ensemble. Si c’est le cas, la méthode du fournisseur de schéma doit ajouter le nouvel élément à l’élément existant XmlSchema. Sinon, il doit créer une instance XmlSchema . Cette opération est importante si les tableaux de types IXmlSerializable sont utilisés. Par exemple, si vous avez un IXmlSerializable type qui est exporté en tant que type « A » dans l’espace de noms « B », il est possible qu’au moment où la méthode du fournisseur de schémas soit appelée le jeu de schémas contient déjà le schéma pour « B » pour contenir le type « ArrayOfA ».

En plus d’ajouter des types au XmlSchemaSet, la méthode du fournisseur de schéma pour les types de contenu doit retourner une valeur non Null. Il peut retourner un XmlQualifiedName qui spécifie le nom du type de schéma à utiliser pour le type IXmlSerializable donné. Ce nom qualifié sert également de nom de contrat de données et d’espace de noms pour le type. Il est permis de retourner un type qui n'existe pas dans l'ensemble de schémas immédiatement lorsque la méthode du fournisseur de schémas est exécutée. Toutefois, il est attendu qu’au moment où tous les types liés sont exportés (la Export méthode est appelée pour tous les types concernés sur l'ensemble XsdDataContractExporter et que la propriété Schemas est accessible), le type existe dans le jeu de schémas. Accéder à la propriété Schemas avant d'effectuer tous les appels Export pertinents peut provoquer une XmlSchemaException. Pour plus d’informations sur le processus d’exportation, consultez Exportation de schémas à partir de classes.

La méthode du fournisseur de schéma peut aussi retourner le XmlSchemaType à utiliser. Le type peut ou non être anonyme. S’il est anonyme, le schéma du IXmlSerializable type est exporté en tant que type anonyme chaque fois que le IXmlSerializable type est utilisé comme membre de données. Le type IXmlSerializable a encore un nom et un espace de noms de contrat de données. (Cela est déterminé comme décrit dans les noms de contrat de données , sauf que l’attribut DataContractAttribute ne peut pas être utilisé pour personnaliser le nom.) S’il n’est pas anonyme, il doit s’agir de l’un des types dans le XmlSchemaSet. Ce cas équivaut à retourner le XmlQualifiedName du type.

En outre, une déclaration d’élément global est exportée pour le type. Si le type n’a pas l’attribut XmlRootAttribute appliqué à celui-ci, l’élément a le même nom et l’espace de noms que le contrat de données, et sa propriété « nillable » est true. La seule exception à ceci est l’espace de noms de schéma (http://www.w3.org/2001/XMLSchema) : si le contrat de données du type se trouve dans cet espace de noms, l’élément global correspondant se trouve dans l’espace de noms vide, car il est interdit d’ajouter de nouveaux éléments à l’espace de noms de schéma. Si le type a l’attribut XmlRootAttribute appliqué, la déclaration d’élément globale est exportée à l’aide des propriétés suivantes : ElementName, Namespace et IsNullable. Les valeurs par défaut appliquées avec XmlRootAttribute sont le nom de contrat de données, un espace de noms vide et « nillable » ayant pour valeur true.

Les mêmes règles de déclaration d’élément globale s’appliquent aux types de jeux de données hérités. Notez que XmlRootAttribute ne peut pas substituer de déclarations d'élément globales ajoutées par l'intermédiaire du code personnalisé, ajoutées soit à XmlSchemaSet à l'aide de la méthode du fournisseur de schéma, soit à l'aide de GetSchema pour les types de groupes de données hérités.

Types d'élément IXmlSerializable

IXmlSerializable les types d'éléments ont soit la propriété IsAny définie sur true, soit leur méthode de fournisseur de schéma retourne null.

La sérialisation et la désérialisation d’un type d’élément sont très similaires à la sérialisation et à la désérialisation d’un type de contenu. Toutefois, il existe des différences importantes :

  • L’implémentation WriteXml est censée écrire exactement un élément (qui peut bien sûr contenir plusieurs éléments enfants). Il ne doit pas écrire d’attributs en dehors de cet élément unique, plusieurs éléments frères ou contenu mixte. L’élément peut être vide.

  • L’implémentation ReadXml ne doit pas lire l’élément wrapper. Elle est censée lire l'élément unique produit par WriteXml.

  • Lors de la sérialisation régulière d’un type d’élément (par exemple, en tant que membre de données dans un contrat de données), le sérialiseur génère un élément wrapper avant d’appeler WriteXml, comme avec les types de contenu. Toutefois, lors de la sérialisation d’un élément de type au niveau supérieur, le sérialiseur ne génère normalement pas d’élément d'encapsulation autour de l’élément que WriteXml écrit, sauf si un nom racine et un espace de noms sont explicitement spécifiés lors de la construction du sérialiseur dans les constructeurs DataContractSerializer ou NetDataContractSerializer. Pour plus d’informations, consultez Sérialisation et Désérialisation.

  • Lors de la sérialisation d’un type d’élément au niveau supérieur sans spécifier le nom racine et l’espace de noms au moment de la construction, WriteStartObject et WriteEndObject ne font essentiellement rien et WriteObjectContent appellent WriteXml. Dans ce mode, l’objet sérialisé ne peut pas être null et ne peut pas être polymorphement affecté. En outre, la préservation du graphique d’objets ne peut être activée, et NetDataContractSerializer ne peut pas être utilisé.

  • Lors de la désérialisation d’un type d’élément au niveau supérieur sans spécifier le nom racine et l’espace de noms au moment de la construction, IsStartObject retourne true s’il peut trouver le début d’un élément. ReadObject avec le paramètre verifyObjectName défini à true se comporte de la même façon que IsStartObject avant de lire l'objet en question. ReadObject passe ensuite le contrôle à la ReadXml méthode.

Le schéma exporté pour les types d’éléments est le même que pour le XmlElement type décrit dans une section précédente, sauf que la méthode du fournisseur de schémas peut ajouter n’importe quel schéma supplémentaire à celui XmlSchemaSet des types de contenu. L’utilisation de l’attribut XmlRootAttribute avec des types d’éléments n’est pas autorisée et les déclarations d’éléments globales ne sont jamais émises pour ces types.

Différences par rapport au XmlSerializer

L'interface IXmlSerializable et les attributs XmlSchemaProviderAttribute et XmlRootAttribute sont également compris par le XmlSerializer. Toutefois, il existe des différences dans la façon dont elles sont traitées dans le modèle de contrat de données. Les différences importantes sont résumées dans la liste suivante :

  • La méthode du fournisseur de schéma doit être publique pour être utilisée dans le XmlSerializermodèle de contrat de données, mais elle ne doit pas être publique.

  • La méthode du fournisseur de schémas est appelée lorsque IsAny est true dans le modèle de contrat de données, mais pas avec le XmlSerializer.

  • Lorsque l’attribut XmlRootAttribute n’est pas présent pour les types de contenu ou les jeux de données hérités, le XmlSerializer exporte une déclaration d’élément global dans l’espace de noms vide. Dans le modèle de contrat de données, l’espace de noms utilisé est normalement l’espace de noms du contrat de données, comme décrit précédemment.

Tenez compte de ces différences lors de la création de types utilisés avec les deux technologies de sérialisation.

Importation du schéma IXmlSerializable

Lors de l’importation d’un schéma généré à partir de IXmlSerializable types, il existe quelques possibilités :

  • Le schéma généré peut être un schéma de contrat de données valide, comme décrit dans la référence du schéma du contrat de données. Dans ce cas, le schéma peut être importé comme d’habitude et les types de contrats de données standard sont générés.

  • Le schéma généré peut ne pas être un schéma de contrat de données valide. Par exemple, votre méthode de fournisseur de schémas peut générer un schéma qui implique des attributs XML qui ne sont pas pris en charge dans le modèle de contrat de données. Dans ce cas, vous pouvez importer le schéma en tant que IXmlSerializable types. Ce mode d’importation n’est pas activé par défaut, mais peut facilement être activé, par exemple, avec le /importXmlTypes commutateur de ligne de commande vers l’outil utilitaire de métadonnées ServiceModel (Svcutil.exe). Cette procédure est décrite en détail dans le schéma d’importation pour générer des classes. Notez que vous devez travailler directement avec le code XML de vos instances de type. Vous pouvez également envisager d’utiliser une technologie de sérialisation différente qui prend en charge un plus large éventail de schémas : consultez la rubrique sur l’utilisation du XmlSerializer.

  • Vous pouvez réutiliser vos types existants IXmlSerializable dans le proxy au lieu de générer de nouveaux types. Dans ce cas, la fonctionnalité de types référencés décrite dans la rubrique Importing Schema to Generate Types peut être utilisée pour indiquer le type à réutiliser. Cela correspond à l'utilisation de l'option /reference sur svcutil.exe, qui spécifie l'assembly contenant les types à réutiliser.

Comportement hérité de XmlSerializer

Dans .NET Framework 4.0 et versions antérieures, xmlSerializer a généré des assemblys de sérialisation temporaires en écrivant du code C# dans un fichier. Le fichier a ensuite été compilé dans un assembly. Ce comportement avait des conséquences indésirables comme ralentir le temps de démarrage du sérialiseur. Dans .NET Framework 4.5, ce comportement a été modifié pour générer les assemblys sans nécessiter l’utilisation du compilateur. Certains développeurs peuvent souhaiter voir le code C# généré. Vous pouvez spécifier d’utiliser ce comportement hérité par la configuration suivante :

<?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>

Si vous rencontrez des problèmes de compatibilité, tels que XmlSerializer échouant à sérialiser une classe dérivée avec une nouvelle substitution non publique, vous pouvez revenir au comportement hérité en utilisant la configuration suivante :

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

En guise d’alternative à la configuration ci-dessus, vous pouvez utiliser la configuration suivante sur un ordinateur exécutant .NET Framework 4.5 ou une version ultérieure :

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

Remarque

Le <xmlSerializer useLegacySerializerGeneration="true"/> commutateur fonctionne uniquement sur un ordinateur exécutant .NET Framework 4.5 ou version ultérieure. L’approche ci-dessus appSettings fonctionne sur toutes les versions de .NET Framework.

Voir aussi