Freigeben über


Verwenden der XmlSerializer-Klasse

Windows Communication Foundation (WCF) kann zwei verschiedene Serialisierungstechnologien verwenden, um die Daten in Ihrer Anwendung in XML umzuwandeln, die zwischen Clients und Diensten übertragen werden: DataContractSerializer und XmlSerializer.

DataContractSerializer

Standardmäßig verwendet WCF die DataContractSerializer Klasse zum Serialisieren von Datentypen. Dieser Serialisierer unterstützt die folgenden Typen:

  • Grundtypen (z. B. Integer, Zeichenfolgen und Bytearrays) sowie einige spezielle Typen, wie XmlElement und DateTime, die als Grundtypen behandelt werden.

  • Datenvertragstypen (Typen, die mit dem DataContractAttribute Attribut gekennzeichnet sind).

  • Typen, die mit dem SerializableAttribute Attribut gekennzeichnet sind, einschließlich Typen, die die ISerializable Schnittstelle implementieren.

  • Typen, die die IXmlSerializable Schnittstelle implementieren.

  • Viele gängige Sammlungstypen, die viele generische Sammlungstypen enthalten.

Viele .NET Framework-Typen fallen in die letzten beiden Kategorien und sind somit serialisierbar. Arrays serialisierbarer Typen sind ebenfalls serialisierbar. Eine vollständige Liste finden Sie unter Angeben der Datenübertragung in Serviceverträgen.

Der DataContractSerializer, der zusammen mit Datenvertragstypen verwendet wird, ist die empfohlene Methode, um neue WCF-Dienste zu schreiben. Weitere Informationen finden Sie unter Verwenden von Datenverträgen.

XmlSerializer

WCF unterstützt auch die XmlSerializer Klasse. Die XmlSerializer Klasse ist nicht für WCF eindeutig. Es ist dasselbe Serialisierungsmodul, das ASP.NET Webdienste verwenden. Die XmlSerializer Klasse unterstützt einen viel engeren Satz von Typen als die DataContractSerializer Klasse, ermöglicht aber viel mehr Kontrolle über das resultierende XML und unterstützt viel mehr vom XSD-Standard (XML Schema Definition Language). Außerdem sind keine deklarativen Attribute für serialisierbare Typen erforderlich. Weitere Informationen finden Sie im Thema zur XML-Serialisierung in der .NET Framework-Dokumentation. Die XmlSerializer Klasse unterstützt keine Datenvertragstypen.

Wenn Sie Svcutil.exe oder das Feature " Dienstreferenz hinzufügen " in Visual Studio verwenden, um Clientcode für einen Drittanbieterdienst zu generieren oder auf ein Drittanbieterschema zuzugreifen, wird automatisch ein entsprechender Serialisierer für Sie ausgewählt. Wenn das Schema nicht mit dem DataContractSerializerSchema kompatibel ist, wird die XmlSerializer Option ausgewählt.

Wechseln zum XmlSerializer

Gelegentlich müssen Sie möglicherweise manuell auf XmlSerializer umschalten. Dies geschieht beispielsweise in den folgenden Fällen:

  • Wenn Sie eine Anwendung von ASP.NET Webdiensten zu WCF migrieren, sollten Sie vorhandene, XmlSerializerkompatible Typen wiederverwenden, anstatt neue Datentypen zu erstellen.

  • Wenn eine genaue Kontrolle über den XML-Code, der in Nachrichten angezeigt wird, wichtig ist, aber ein WSDL-Dokument (Web Services Description Language) nicht verfügbar ist, z. B. beim Erstellen eines Diensts mit Typen, die einem bestimmten standardisierten, veröffentlichten Schema entsprechen müssen, das nicht mit dem DataContractSerializer kompatibel ist.

  • Beim Erstellen von Diensten, die dem älteren SOAP-Codierungsstandard entsprechen.

In diesen und anderen Fällen können Sie manuell zur XmlSerializer Klasse wechseln, indem Sie das XmlSerializerFormatAttribute Attribut auf Ihren Dienst anwenden, wie im folgenden Code gezeigt.

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

Sicherheitsüberlegungen

Hinweis

Es ist wichtig, beim Wechsel von Serialisierungs-Engines vorsichtig zu sein. Je nach verwendetem Serializer kann derselbe Typ unterschiedlich in XML serialisiert werden. Wenn Sie versehentlich den falschen Serialisierer verwenden, geben Sie möglicherweise Informationen aus dem Typ an, den Sie nicht offenlegen wollten.

Die DataContractSerializer Klasse serialisiert beispielsweise nur die Mitglieder, die mit dem DataMemberAttribute Attribut gekennzeichnet sind, wenn Datenvertrags-Typen serialisiert werden. Die XmlSerializer-Klasse serialisiert jeden öffentlichen Member. Sehen Sie sich den Typ im folgenden Code an.

[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

Wenn der Typ versehentlich in einem Dienstvertrag verwendet wird, in dem die XmlSerializer Klasse ausgewählt ist, wird das creditCardNumber Element serialisiert, was wahrscheinlich nicht beabsichtigt ist.

Obwohl die DataContractSerializer Klasse der Standard ist, können Sie sie explizit für Ihren Dienst auswählen (obwohl dies nie erforderlich sein sollte), indem Sie das DataContractFormatAttribute Attribut auf den Dienstvertragstyp anwenden.

Der für den Dienst verwendete Serialisierer ist ein integraler Bestandteil des Vertrags und kann nicht geändert werden, indem er eine andere Bindung auswählt oder andere Konfigurationseinstellungen ändert.

Andere wichtige Sicherheitsaspekte gelten für die XmlSerializer Klasse. Zunächst wird dringend empfohlen, dass jede WCF-Anwendung, die die XmlSerializer Klasse verwendet, mit einem Schlüssel signiert ist, der vor der Offenlegung geschützt ist. Diese Empfehlung gilt sowohl, wenn ein manueller Wechsel zu XmlSerializer erfolgt, als auch, wenn ein automatischer Wechsel erfolgt (durch Svcutil.exe, Dienstverweis hinzufügen oder ein ähnliches Tool). Dies liegt daran, dass das XmlSerializer Serialisierungsmodul das Laden von vorgenerierten Serialisierungsassemblys unterstützt, solange sie mit demselben Schlüssel wie die Anwendung signiert sind. Eine nicht signierte Anwendung ist völlig ungeschützt vor der Möglichkeit, dass eine böswillige Assembly mit dem erwarteten Namen der vorgenerierten Serialisierungsassembly im Anwendungsordner oder im globalen Assemblycache abgelegt wird. Natürlich muss ein Angreifer zunächst Schreibzugriff auf einen dieser beiden Speicherorte erhalten, um diese Aktion zu versuchen.

Eine weitere Bedrohung, die immer vorhanden ist, wenn Sie XmlSerializer verwenden, besteht im Zusammenhang mit dem Schreibzugriff auf den temporären Systemordner. Die XmlSerializer Serialisierungs-Engine erstellt und verwendet temporäre Serialisierungsassemblies in diesem Ordner. Beachten Sie, dass jeder Prozess mit Schreibzugriff auf den temporären Ordner diese Serialisierungsassemblys mit bösartigem Code überschreiben kann.

Regeln für xmlSerializer-Unterstützung

Sie können Attribute, die XmlSerializer-kompatibel sind, nicht direkt auf Vertragsvorgangsparameter oder Rückgabewerte anwenden. Sie können jedoch auf eingegebene Nachrichten (Nachrichten-Vertragstextteile) angewendet werden, wie im folgenden Code dargestellt.

[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

Wenn diese Attribute auf eingegebene Nachrichtenelemente angewendet werden, überschreiben diese Attribute Eigenschaften, die mit den typierten Nachrichtenattributen in Konflikt geraten. Im folgenden Code setzt zum Beispiel ElementNameName außer Kraft.

    [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

Das MessageHeaderArrayAttribute Attribut wird bei Verwendung des Attributs XmlSerializernicht unterstützt.

Hinweis

In diesem Fall löst die XmlSerializer folgende Ausnahme aus, die vor WCF veröffentlicht wird: "Ein Element, das auf der obersten Ebene eines Schemas deklariert ist, darf 1 nicht aufweisen maxOccurs> . Stellen Sie ein Wrapperelement für "more" bereit, indem Sie entweder XmlArray oder das Wrapped-Parameterformat verwenden oder XmlArrayItem anstelle von XmlElementAttribute verwenden.

Wenn Sie eine solche Ausnahme erhalten, untersuchen Sie, ob diese Situation zutrifft.

WCF unterstützt die Attribute SoapIncludeAttribute und XmlIncludeAttribute in Nachrichtenverträgen und Operationsverträgen nicht; verwenden Sie stattdessen das KnownTypeAttribute Attribut.

Typen, die die IXmlSerializable-Schnittstelle implementieren

Typen, die die IXmlSerializable Schnittstelle implementieren, werden vollständig von der DataContractSerializer unterstützt. Das XmlSchemaProviderAttribute Attribut sollte immer auf diese Typen angewendet werden, um das Schema zu steuern.

Warnung

Wenn Sie polymorphe Typen serialisieren, müssen Sie das XmlSchemaProviderAttribute-Tag auf den Typ anwenden, um sicherzustellen, dass der richtige Typ serialisiert wird.

Es gibt drei Arten von Typen, die implementieren IXmlSerializable: Typen, die beliebige Inhalte darstellen, Typen, die ein einzelnes Element darstellen, und Legacytypen DataSet .

  • Inhaltstypen verwenden eine vom XmlSchemaProviderAttribute Attribut angegebene Schemaanbietermethode. Die Methode gibt nicht zurück null , und die IsAny Eigenschaft für das Attribut bleibt am Standardwert von false. Dies ist die am häufigsten verwendete Verwendung von IXmlSerializable Typen.

  • Elementtypen werden verwendet, wenn ein IXmlSerializable Typ seinen eigenen Stammelementnamen steuern muss. Wenn Sie einen Typ als Elementtyp markieren möchten, legen Sie entweder die IsAny Eigenschaft für das XmlSchemaProviderAttribute Attribut auf true, oder Sie geben null von der Schemaanbietermethode zurück. Eine Schemaanbietermethode ist für Elementtypen optional – Sie können null anstelle des Methodennamens in XmlSchemaProviderAttribute angeben. Wenn IsAnytrue ist und eine Schemaanbietermethode angegeben ist, muss die Methode null zurückgeben.

  • Legacy-Typen DataSet sind IXmlSerializable Typen, die nicht mit dem XmlSchemaProviderAttribute Attribut gekennzeichnet sind. Stattdessen basieren sie auf der Methode für die GetSchema Schemagenerierung. Dieses Muster wird für den DataSet-Typ verwendet, und sein typisiertes Dataset leitet in früheren Versionen des .NET Frameworks eine Klasse ab, ist jedoch inzwischen obsolet und wird nur aus Gründen der Kompatibilität unterstützt. Verlassen Sie sich nicht auf dieses Muster, sondern wenden Sie immer XmlSchemaProviderAttribute auf Ihre IXmlSerializable-Typen an.

IXmlSerialisierbare Inhaltstypen

Beim Serialisieren eines Datenmitglieds eines Typs, der IXmlSerializable implementiert und als Inhaltstyp wie zuvor definiert wurde, schreibt der Serialisierer das Wrapperelement für das Datenmitglied und übergibt die Steuerung an die WriteXml-Methode. Die WriteXml Implementierung kann einen beliebigen XML-Code schreiben, der das Hinzufügen von Attributen zum Wrapperelement enthält. Nachdem WriteXml abgeschlossen ist, schließt das Serialisierungsprogramm das Element.

Wenn Sie einen Datenmember eines Typs deserialisieren, der IXmlSerializable implementiert und ein wie zuvor definierter Inhaltstyp ist, ordnet das Deserialisierungsprogramm den XML-Reader im Wrapperelement für den Datenmember an und übergibt die Steuerung an die ReadXml-Methode. Die Methode muss das gesamte Element einschließlich der Start- und Endtags lesen. Stellen Sie sicher, dass ihr ReadXml Code den Fall behandelt, in dem das Element leer ist. Darüber hinaus sollte Ihre ReadXml Implementierung nicht darauf angewiesen sein, dass das Wrapperelement auf eine bestimmte Weise benannt ist. Der Name wird vom Serialisierer ausgewählt, kann variieren.

Es ist gestattet, Inhaltstypen polymorph zuzuweisenIXmlSerializable, z. B. an Datenmitglieder des Typs Object. Es ist auch zulässig, dass die Typinstanzen null sind. Schließlich ist es möglich, IXmlSerializable-Typen mit aktivierter Objektdiagramm-Erhaltung und mit dem NetDataContractSerializer zu verwenden. Alle diese Features erfordern den WCF-Serialisierer, um bestimmte Attribute an das Wrapperelement anzufügen, darunter "nil" und "type" im XML-Schemainstanz-Namespace sowie "Id", "Ref", "Type" und "Assembly" in einem WCF-spezifischen Namespace.

Attribute, die ignoriert werden, wenn ReadXml implementiert wird

Bevor Sie die Steuerung an Ihren ReadXml Code übergeben, überprüft der Deserializer das XML-Element, erkennt diese speziellen XML-Attribute und wirkt darauf. Wenn beispielsweise "nil" lautet true, wird ein Nullwert deserialisiert und ReadXml nicht aufgerufen. Wenn Polymorphismus erkannt wird, werden die Inhalte des Elements deserialisiert, als wäre es ein anderer Typ. Die ReadXml-Implementierung des polymorph zugewiesenen Typs wird aufgerufen. In jedem Fall sollte eine ReadXml Implementierung diese speziellen Attribute ignorieren, da sie vom Deserializer behandelt werden.

Schemaüberlegungen für IXmlSerializable-Inhaltstypen

Beim Exportieren des Schemas und eines IXmlSerializable Inhaltstyps wird die Schemaanbietermethode aufgerufen. Ein XmlSchemaSet wird an die Schemaanbieter-Methode übergeben. Die Methode kann dem Schemasatz ein beliebiges gültiges Schema hinzufügen. Der Schemasatz enthält das Schema, das zum Zeitpunkt des Schemaexports bereits bekannt ist. Wenn die Schemaanbietermethode dem Schemasatz ein Element hinzufügen muss, muss ermittelt werden, ob ein XmlSchema Mit dem entsprechenden Namespace bereits im Satz vorhanden ist. Wenn dies der Fall ist, muss die Schemaanbietermethode das neue Element zum vorhandenen XmlSchema hinzufügen. Andernfalls muss eine neue XmlSchema Instanz erstellt werden. Dies ist wichtig, wenn Arrays von IXmlSerializable Typen verwendet werden. Wenn Sie z. B. über einen IXmlSerializable Typ verfügen, der als Typ "A" im Namespace "B" exportiert wird, ist es möglich, dass die Schemaanbietermethode nach dem Zeitpunkt, zu dem die Schemaanbietermethode aufgerufen wird, bereits das Schema für "B" enthält, um den "ArrayOfA"-Typ zu enthalten.

Zusätzlich zum Hinzufügen von Typen zu XmlSchemaSet muss die Schemaanbietermethode für Inhaltstypen einen Wert zurückgeben, der nicht null ist. Sie kann einen XmlQualifiedName Wert zurückgeben, der den Namen des Schematyps angibt, der für den angegebenen IXmlSerializable Typ verwendet werden soll. Dieser qualifizierte Name dient auch als Datenvertragsname und Namespace für den Typ. Es ist zulässig, einen Typ zurückzugeben, der im Schemasatz nicht sofort vorhanden ist, wenn die Schemaanbietermethode zurückgegeben wird. Es wird jedoch vorausgesetzt, dass der Typ nach dem Export aller verwandten Typen (die Export-Methode wird für alle relevanten Typen von XsdDataContractExporter aufgerufen, und es wird auf die Schemas-Eigenschaft zugegriffen) im Schemasatz vorhanden ist. Das Zugreifen auf die Schemas-Eigenschaft, bevor alle relevanten Export-Aufrufe durchgeführt wurden, kann zu einer XmlSchemaException führen. Weitere Informationen zum Exportprozess finden Sie unter Exportieren von Schemas aus Klassen.

Die Schemaanbietermethode kann auch den zu verwendenden XmlSchemaType zurückgeben. Der Typ kann anonym sein oder auch nicht. Wenn es anonym ist, wird das Schema für den IXmlSerializable Typ jedes Mal als anonymer Typ exportiert, wenn der IXmlSerializable Typ als Datenmememm verwendet wird. Der IXmlSerializable Typ verfügt weiterhin über einen Datenvertragsnamen und einen Namespace. (Dies wird wie in Den Datenvertragsnamen beschrieben festgelegt, mit der Ausnahme, dass das DataContractAttribute Attribut nicht zum Anpassen des Namens verwendet werden kann.) Wenn es nicht anonym ist, muss es sich um einen der Typen in der XmlSchemaSet. Dies entspricht dem Zurückgeben von XmlQualifiedName für den Typ.

Darüber hinaus wird eine globale Elementdeklaration für den Typ exportiert. Wenn das XmlRootAttribute-Attribut nicht auf den Typ angewendet wurde, hat das Element denselben Namen und denselben Namespace wie der Datenvertrag, und seine Eigenschaft "nullfähig" ist true. Die einzige Ausnahme ist der Schemanamespace (http://www.w3.org/2001/XMLSchema) – wenn sich der Datenvertrag des Typs in diesem Namespace befindet, befindet sich das entsprechende globale Element im leeren Namespace, da es verboten ist, dem Schemanamespace neue Elemente hinzuzufügen. Wenn der Typ das XmlRootAttribute Attribut zugewiesen ist, wird die globale Elementdeklaration mithilfe der folgenden Eigenschaften exportiert: ElementName, Namespace und IsNullable. Die Standardwerte mit XmlRootAttribute sind der Name des Datenvertrags, ein leerer Namespace und "nullfähig" ist true.

Die gleichen regeln für die globale Elementdeklaration gelten für ältere Datasettypen. Beachten Sie, dass XmlRootAttribute die globalen Elementdeklarationen, die über benutzerdefinierten Code hinzugefügt wurden, nicht überschreiben kann, die entweder unter Verwendung der Schemaanbietermethode XmlSchemaSet oder über GetSchema für ältere Datensatztypen hinzugefügt wurden.

IXmlSerializable-Elementtypen

Für IXmlSerializable-Elementtypen ist entweder die IsAny-Eigenschaft auf true festgelegt, oder ihre Schemaanbietermethode gibt null zurück.

Die Serialisierung und Deserialisierung eines Elementtyps ähnelt der Serialisierung und Deserialisierung eines Inhaltstyps. Es gibt jedoch einige wichtige Unterschiede:

  • Von der WriteXml-Implementierung wird erwartet, dass sie genau ein Element schreibt (das natürlich mehrere untergeordnete Elemente enthalten kann). Sie sollte keine Attribute außerhalb dieses einzelnen Elements, mehrerer gleichgeordneter Elemente oder gemischten Inhalts schreiben. Das Element ist möglicherweise leer.

  • Die ReadXml Implementierung sollte das Wrapperelement nicht lesen. Es wird erwartet, dass sie das einzelne Element liest, das von WriteXml erzeugt wird.

  • Beim regelmäßigen Serialisieren eines Elementtyps (z. B. als Datenmitglied in einem Datenvertrag) gibt der Serialisierer ein Wrapperelement aus, bevor er wie bei Inhaltstypen WriteXml aufruft. Bei der Serialisierung eines Elementtyps auf oberster Ebene gibt der Serializer normalerweise kein Wrapperelement um das Element aus, das WriteXml schreibt, es sei denn, ein Stammname und ein Namespace werden explizit angegeben, wenn der Serializer mit den Konstruktoren DataContractSerializer oder NetDataContractSerializer erstellt wird. Weitere Informationen finden Sie unter Serialisierung und Deserialisierung.

  • Beim Serialisieren eines Elementtyps auf der obersten Ebene ohne Angabe des Stammnamens und des Namespaces zur Erstellungszeit tun WriteStartObject und WriteEndObject im Wesentlichen nichts, während WriteObjectContentWriteXml aufruft. In diesem Modus kann das zu serialisierende Objekt nicht null sein und kann nicht polymorph zugewiesen werden. Außerdem kann die Objektdiagramm-Erhaltung nicht aktiviert werden, und das NetDataContractSerializer kann nicht verwendet werden.

  • Wenn Sie einen Elementtyp auf der obersten Ebene deserialisieren, ohne den Stammnamen und den Namespace zur Erstellungszeit anzugeben, gibt IsStartObjecttrue zurück, wenn der Anfang eines Elements gefunden werden kann. ReadObject mit dem verifyObjectName-Parameter auf true gesetzt, verhält sich auf die gleiche Weise wie IsStartObject, bevor das Objekt tatsächlich gelesen wird. ReadObject übergibt anschließend die Steuerung an die ReadXml-Methode.

Das für Elementtypen exportierte Schema ist identisch mit dem XmlElement Typ, der in einem früheren Abschnitt beschrieben wird, mit der Ausnahme, dass die Schemaanbietermethode dem XmlSchemaSet Typ zusätzliches Schema hinzufügen kann, ähnlich wie bei Inhaltstypen. Die Verwendung des XmlRootAttribute Attributs mit Elementtypen ist nicht zulässig, und globale Elementdeklarationen werden für diese Typen nie ausgegeben.

Unterschiede zum XmlSerializer

Die IXmlSerializable Schnittstelle und die Attribute XmlSchemaProviderAttribute und XmlRootAttribute werden ebenfalls von XmlSerializer verstanden. Es gibt jedoch einige Unterschiede bei der Behandlung dieser Daten im Datenvertragsmodell. Die wichtigen Unterschiede sind in der folgenden Liste zusammengefasst:

  • Die Schemaanbietermethode muss im XmlSerializer öffentlich sein, um verwendet zu werden, muss jedoch im Datenvertragsmodell nicht öffentlich sein.

  • Die Schemaanbietermethode wird aufgerufen, wenn für IsAny im Datenvertragsmodell true gilt, jedoch nicht für den XmlSerializer.

  • Wenn das XmlRootAttribute Attribut nicht für Inhalts- oder Legacy-Datasettypen vorhanden ist, exportiert dies XmlSerializer eine globale Elementdeklaration im leeren Namespace. Im Datenvertragsmodell ist der verwendete Namespace normalerweise der Datenvertragsnamespace, wie zuvor beschrieben.

Beachten Sie diese Unterschiede beim Erstellen von Typen, die mit beiden Serialisierungstechnologien verwendet werden.

Importieren eines IXmlSerializable-Schemas

Beim Importieren eines schemas, das aus IXmlSerializable Typen generiert wird, gibt es einige Möglichkeiten:

  • Das generierte Schema kann ein gültiges Datenvertragsschema sein, wie in der Datenvertragsschemareferenz beschrieben. In diesem Fall kann das Schema wie gewohnt importiert werden, und reguläre Datavertragstypen werden generiert.

  • Das generierte Schema ist möglicherweise kein gültiges Datenvertragsschema. Ihre Schemaanbietermethode kann z. B. Schema generieren, das XML-Attribute umfasst, die im Datenvertragsmodell nicht unterstützt werden. In diesem Fall können Sie das Schema als IXmlSerializable Typen importieren. Dieser Importmodus ist nicht standardmäßig aktiviert, kann aber problemlos aktiviert werden – z. B. mit dem /importXmlTypes Befehlszeilenwechsel zum Metadatenhilfsprogramm ServiceModel (Svcutil.exe). Dies wird im Importschema zum Generieren von Klassen ausführlich beschrieben. Beachten Sie, dass Sie direkt mit dem XML-Code für Ihre Typinstanzen arbeiten müssen. Sie können auch eine andere Serialisierungstechnologie verwenden, die eine breitere Palette von Schemas unterstützt . Weitere Informationen finden Sie im Thema zur Verwendung des XmlSerializerSchemas.

  • Möglicherweise möchten Sie Ihre vorhandenen IXmlSerializable Typen im Proxy wiederverwenden, anstatt neue zu generieren. In diesem Fall kann das im Thema "Importieren von Schema zum Generieren von Typen" beschriebene Feature für referenzierte Typen verwendet werden, um den Typ anzugeben, der wiederverwendet werden soll. Dies entspricht dem Verwenden des Schalters /reference für „svcutil.exe“. Damit wird die Assembly angegeben, die die wiederzuverwendenden Typen enthält.

XmlSerializer-Legacyverhalten

In .NET Framework 4.0 und früher generierte der XmlSerializer temporäre Serialisierungsassemblys durch Schreiben von C#-Code in eine Datei. Die Datei wurde dann in eine Assembly kompiliert. Dieses Verhalten hatte einige unerwünschte Folgen, z. B. das Verlangsamen der Startzeit für den Serialisierer. In .NET Framework 4.5 wurde dieses Verhalten geändert, um die Assemblys zu generieren, ohne dass der Compiler verwendet werden muss. Einige Entwickler möchten möglicherweise den generierten C#-Code sehen. Sie können angeben, dass dieses Legacyverhalten durch die folgende Konfiguration verwendet werden soll:

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

Wenn Kompatibilitätsprobleme auftreten, z. B. XmlSerializer-Fehler beim Serialisieren einer abgeleiteten Klasse mit einer nicht öffentlichen neuen Überschreibung, können Sie mithilfe der folgenden Konfiguration zurück zum Legacyverhalten von XMLSerializer wechseln:

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

Als Alternative zur obigen Konfiguration können Sie die folgende Konfiguration auf einem Computer verwenden, auf dem .NET Framework 4.5 oder höher ausgeführt wird:

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

Hinweis

Der <xmlSerializer useLegacySerializerGeneration="true"/> Switch funktioniert nur auf einem Computer mit .NET Framework 4.5 oder höher. Der obige appSettings Ansatz funktioniert für alle .NET Framework-Versionen.

Siehe auch