Serialisierung und DeserialisierungSerialization and Deserialization

Windows Communication Foundation (WCF)Windows Communication Foundation (WCF) umfasst ein neues Serialisierungsmodul, DataContractSerializer. includes a new serialization engine, the DataContractSerializer. DataContractSerializer übersetzt .NET Framework.NET Framework -Objekte in XML (und umgekehrt).The DataContractSerializer translates between .NET Framework.NET Framework objects and XML, in both directions. In diesem Thema wird die Funktionsweise des Serialisierungsprogramms erklärt.This topic explains how the serializer works.

Beim Serialisieren von .NET Framework.NET Framework -Objekten erkennt das Serialisierungsprogramm verschiedene Serialisierungsprogrammiermodelle, einschließlich des neuen Datenvertrag smodells.When serializing .NET Framework.NET Framework objects, the serializer understands a variety of serialization programming models, including the new data contract model. Eine vollständige Liste der unterstützten Typen finden Sie unter Types Supported by the Data Contract Serializer.For a full list of supported types, see Types Supported by the Data Contract Serializer. Eine Einführung in Datenverträge finden Sie unter Using Data Contracts.For an introduction to data contracts, see Using Data Contracts.

Beim Deserialisieren von XML verwendet das Serialisierungsprogramm die XmlReader -Klasse und die XmlWriter -Klasse.When deserializing XML, the serializer uses the XmlReader and XmlWriter classes. Zudem werden die XmlDictionaryReader -Klasse und die XmlDictionaryWriter -Klasse unterstützt, damit in bestimmten Fällen optimiertes XML erzeugt werden kann, beispielsweise beim Einsatz des binären XML-Formats von WCFWCF .It also supports the XmlDictionaryReader and XmlDictionaryWriter classes to enable it to produce optimized XML in some cases, such as when using the WCFWCF binary XML format.

WCFWCF beinhaltet auch ein zugehöriges Serialisierungsprogramm namens NetDataContractSerializer. also includes a companion serializer, the NetDataContractSerializer. NetDataContractSerializer ähnelt den Serialisierungsprogrammen BinaryFormatter und SoapFormatter , da auch hier .NET Framework.NET Framework -Typnamen zusammen mit den serialisierten Daten ausgegeben werden.The NetDataContractSerializer is similar to the BinaryFormatter and SoapFormatter serializers because it also emits .NET Framework.NET Framework type names as part of the serialized data. Es wird verwendet, wenn die Endpunkte, die die Serialisierung und die Deserialisierung durchführen, die gleichen Datentypen verwenden.It is used when the same types are shared on the serializing and the deserializing ends. Sowohl DataContractSerializer als auch NetDataContractSerializer sind von der gemeinsamen Basisklasse XmlObjectSerializerabgeleitet.Both the DataContractSerializer and the NetDataContractSerializer derive from a common base class, the XmlObjectSerializer.

Warnung

Der DataContractSerializer serialisiert Zeichenfolgen mit Steuerzeichen mit einem Hexadezimalwert kleiner als 20 als XML-Entitäten.The DataContractSerializer serializes strings containing control characters with a hexadecimal value below 20 as XML entities. Dies kann ein Problem mit einem nicht-WCF-Client führen, wenn solche Daten an einen WCF-Dienst zu senden.This may cause a problem with a non-WCF client when sending such data to a WCF service.

Erstellen einer DataContractSerializer-InstanzCreating a DataContractSerializer Instance

Das Erstellen einer DataContractSerializer -Instanz ist ein wichtiger Schritt.Constructing an instance of the DataContractSerializer is an important step. Sie können nach der Erstellung dieser Instanz keine Einstellungen mehr ändern.After construction, you cannot change any of the settings.

Angeben des StammtypsSpecifying the Root Type

Der Stammtyp ist der Typ, von dem Instanzen serialisiert oder deserialisiert werden.The root type is the type of which instances are serialized or deserialized. Für DataContractSerializer sind viele überladene Konstruktoren verfügbar; aber mindestens ein Stammtyp muss mit dem Parameter type angegeben werden.The DataContractSerializer has many constructor overloads, but, at a minimum, a root type must be supplied using the type parameter.

Ein für einen bestimmten Stammtyp erstelltes Serialisierungsprogramm kann nur dann zum Serialisieren (oder Deserialisieren) eines anderen Typs verwendet werden, wenn dieser Typ vom Stammtyp abgeleitet ist.A serializer created for a certain root type cannot be used to serialize (or deserialize) another type, unless the type is derived from the root type. Das folgende Beispiel zeigt zwei Klassen.The following example shows two classes.

[DataContract]
public class Person
{
    // Code not shown.
}

[DataContract]
public class PurchaseOrder
{
    // Code not shown.
}
<DataContract()> _
Public Class Person
    ' Code not shown.
End Class 

<DataContract()> _
Public Class PurchaseOrder
    ' Code not shown.
End Class 

In diesem Code wird eine Instanz der DataContractSerializer -Klasse erstellt, die lediglich zum Serialisieren und Deserialisieren der Person -Klasse verwendet werden kann.This code constructs an instance of the DataContractSerializer that can be used only to serialize or deserialize instances of the Person class.

DataContractSerializer dcs = new DataContractSerializer(typeof(Person));
// This can now be used to serialize/deserialize Person but not PurchaseOrder.
Dim dcs As New DataContractSerializer(GetType(Person))
' This can now be used to serialize/deserialize Person but not PurchaseOrder.

Angeben von bekannten TypenSpecifying Known Types

Wenn die serialisierten Typen polymorph sind und die Polymorphie nicht bereits mithilfe des KnownTypeAttribute -Attributs oder eines anderen Mechanismus gehandhabt wird, dann muss dem Konstruktor der Serializer-Instanz im knownTypes -Parameter eine Liste der möglichen bekannten Typen übergeben werden.If polymorphism is involved in the types being serialized that is not already handled using the KnownTypeAttribute attribute or some other mechanism, a list of possible known types must be passed to the serializer’s constructor using the knownTypes parameter. Weitere Informationen finden Sie unterFor more information about zu bekannten Typen finden Sie unter Data Contract Known Types. known types, see Data Contract Known Types.

Im folgenden Codebeispiel wird die Klasse namens LibraryPatronveranschaulicht, die eine Auflistung des Typs LibraryItementhält.The following example shows a class, LibraryPatron, that includes a collection of a specific type, the LibraryItem. Die zweite Klasse definiert den LibraryItem -Typ.The second class defines the LibraryItem type. Die dritte Klasse und die vierte Klasse (Book und Newspaper) sind von der LibraryItem -Klasse abgeleitet.The third and four classes (Book and Newspaper) inherit from the LibraryItem class.

[DataContract]
public class LibraryPatron
{
    [DataMember]
    public LibraryItem[] borrowedItems;
}
[DataContract]
public class LibraryItem
{
    // Code not shown.
}

[DataContract]
public class Book : LibraryItem
{
    // Code not shown.
}

[DataContract]
public class Newspaper : LibraryItem
{
    // Code not shown.
}
<DataContract()>  _
Public Class LibraryPatron
    <DataMember()> _
    Public borrowedItems() As LibraryItem
End Class 

<DataContract()>  _
Public Class LibraryItem
   ' Code not shown.
End Class 'LibraryItem

<DataContract()>  _
Public Class Book
    Inherits LibraryItem
    ' Code not shown.
End Class 

<DataContract()>  _
Public Class Newspaper
    Inherits LibraryItem
    ' Code not shown.
End Class 

Im folgenden Code wird unter Angabe des knownTypes -Parameters eine Serializer-Instanz erstellt.The following code constructs an instance of the serializer using the knownTypes parameter.

// Create a serializer for the inherited types using the knownType parameter.
Type[] knownTypes = new Type[] { typeof(Book), typeof(Newspaper) };
DataContractSerializer dcs =
new DataContractSerializer(typeof(LibraryPatron), knownTypes);
// All types are known after construction.
' Create a serializer for the inherited types using the knownType parameter.
Dim knownTypes() As Type = {GetType(Book), GetType(Newspaper)}
Dim dcs As New DataContractSerializer(GetType(LibraryPatron), knownTypes)
' All types are known after construction.

Angeben von Standardstammnamen und -namespaceSpecifying the Default Root Name and Namespace

Wenn ein Objekt serialisiert wird, werden der Standardname und der Namespace des äußersten XML-Elements in der Regel anhand des Namens und Namespace des Datenvertrags bestimmt.Normally, when an object is serialized, the default name and namespace of the outermost XML element are determined according to the data contract name and namespace. Die Namen aller inneren Elemente werden aus den Datenmembernamen ermittelt, und als Namespace wird ihnen der Namespace des Datenvertrags zugeordnet.The names of all inner elements are determined from data member names, and their namespace is the data contract’s namespace. Im folgenden Beispiel werden die Werte für Name und Namespace in den Konstruktoren für die DataContractAttribute -Klasse und die DataMemberAttribute -Klasse festgelegt.The following example sets Name and Namespace values in the constructors of the DataContractAttribute and DataMemberAttribute classes.

[DataContract(Name = "PersonContract", Namespace = "http://schemas.contoso.com")]
public class Person2
{
    [DataMember(Name = "AddressMember")]
    public Address theAddress;
}

[DataContract(Name = "AddressContract", Namespace = "http://schemas.contoso.com")]
public class Address
{
    [DataMember(Name = "StreetMember")]
    public string street;
}
<DataContract(Name := "PersonContract", [Namespace] := "http://schemas.contoso.com")>  _
Public Class Person2
    <DataMember(Name := "AddressMember")>  _
    Public theAddress As Address
End Class 

<DataContract(Name := "AddressContract", [Namespace] := "http://schemas.contoso.com")>  _
Public Class Address
    <DataMember(Name := "StreetMember")>  _
    Public street As String
End Class 

Durch die Serialisierung einer Instanz der Person -Klasse wird eine XML-Ausgabe erzeugt, die folgendem XML-Code ähnelt.Serializing an instance of the Person class produces XML similar to the following.

<PersonContract xmlns="http://schemas.contoso.com">  
  <AddressMember>  
    <StreetMember>123 Main Street</StreetMember>  
   </AddressMember>  
</PersonContract>  

Sie können den Standardnamen und den Namespace des Stammelements anpassen, indem Sie Werte für den rootName -Parameter und den rootNamespace -Parameter dem DataContractSerializer -Konstruktor übergeben.However, you can customize the default name and namespace of the root element by passing the values of the rootName and rootNamespace parameters to the DataContractSerializer constructor. Beachten Sie, dass sich der rootNamespace -Parameter nicht auf den Namespace der darin enthaltenen Elemente auswirkt, die Datenmembern entsprechen.Note that the rootNamespace does not affect the namespace of the contained elements that correspond to data members. Die Parameterangabe betrifft nur den Namespace des äußersten Elements.It affects only the namespace of the outermost element.

Diese Werte können als Zeichenfolgen oder als Instanzen der XmlDictionaryString -Klasse übergeben werden, damit sie unter Verwendung des binären XML-Formats optimiert werden können.These values can be passed as strings or instances of the XmlDictionaryString class to allow for their optimization using the binary XML format.

Festlegen des maximalen ObjektkontingentsSetting the Maximum Objects Quota

Einige DataContractSerializer -Konstruktorüberladungen verfügen über den maxItemsInObjectGraph -Parameter.Some DataContractSerializer constructor overloads have a maxItemsInObjectGraph parameter. Dieser Parameter legt die maximale Anzahl von Objekten fest, die das Serialisierungsprogramm in einem ReadObject -Methodenaufruf serialisieren oder deserialisieren kann.This parameter determines the maximum number of objects the serializer serializes or deserializes in a single ReadObject method call. (Die Methode liest immer ein Stammobjekt, aber dieses Objekt kann in seinen Datenmembern andere Objekte enthalten.(The method always reads one root object, but this object may have other objects in its data members. Diese Objekte können wiederum andere Objekte enthalten usw.) Der Standard ist 65536.Those objects may have other objects, and so on.) The default is 65536. Beachten Sie, dass beim Serialisieren und Deserialisieren von Arrays jeder Arrayeintrag als separates Objekt betrachtet wird.Note that when serializing or deserializing arrays, every array entry counts as a separate object. Beachten Sie zudem, dass einige Objekte über eine große Speicherdarstellung verfügen und dass dieses Kontingent allein daher möglicherweise nicht ausreicht, um einen Denial-of-Service-Angriff zu verhindern.Also, note that some objects may have a large memory representation, and so this quota alone may not be sufficient to prevent a denial of service attack. Weitere Informationen finden Sie unterFor more information, seeSicherheitsüberlegungen zu Daten. Security Considerations for Data. Wenn Sie das Kontingent über die Standardeinstellung hinaus erhöhen müssen, müssen Sie dies unbedingt sowohl auf der sendenden (serialisierenden) als auch der empfangenden (deserialisierenden) Seite tun, da das Kontingent sowohl für das Lesen als auch das Schreiben von Daten gilt.If you need to increase this quota beyond the default value, it is important to do so both on the sending (serializing) and receiving (deserializing) sides because it applies to both when reading and writing data.

RoundtripsRound Trips

Ein Roundtrip tritt auf, wenn ein Objekt in einem Vorgang deserialisiert und erneut serialisiert wird.A round trip occurs when an object is deserialized and re-serialized in one operation. Das heißt, Daten werden aus XML in eine Objektinstanz und wieder zurück in einen XML-Stream umgewandelt.Thus, it goes from XML to an object instance, and back again into an XML stream.

Einige DataContractSerializer -Konstruktorüberladungen verfügen über den ignoreExtensionDataObject -Parameter, der standardmäßig auf false festgelegt ist.Some DataContractSerializer constructor overloads have an ignoreExtensionDataObject parameter, which is set to false by default. In diesem Standardmodus können Daten von einer neueren Version des Datenvertrags zu einer älteren Datenvertragsversion und wieder zurück zur neueren Version geschickt werden, ohne dass Datenverluste auftreten, sofern der Datenvertrag die IExtensibleDataObject -Schnittstelle implementiert.In this default mode, data can be sent on a round trip from a newer version of a data contract through an older version and back to the newer version without loss, as long as the data contract implements the IExtensibleDataObject interface. Nehmen wir beispielsweise an, Version&#160;1 des Person -Datenvertrags enthält die Datenmember Name und PhoneNumber , und in Version&#160;2 wurde der Member Nickname hinzugefügt.For example, suppose version 1 of the Person data contract contains the Name and PhoneNumber data members, and version 2 adds a Nickname member. Wenn IExtensibleDataObject implementiert wurde, dann werden beim Senden der Daten von Version 2 an Version 1 die Nickname -Daten gespeichert und beim erneuten Serialisieren der Daten wieder ausgegeben. Daher gehen in Roundtrips keine Daten verloren.If IExtensibleDataObject is implemented, when sending information from version 2 to version 1, the Nickname data is stored, and then re-emitted when the data is serialized again; therefore, no data is lost in the round trip. Weitere Informationen finden Sie unterFor more information, seeAufwärtskompatible Datenverträge und Versionsverwaltung von Datenverträgen. Forward-Compatible Data Contracts and Data Contract Versioning.

Bedenken hinsichtlich der Sicherheit und Schemavalidierung bei RoundtripsSecurity and Schema Validity Concerns with Round Trips

Roundtrips beeinträchtigen möglicherweise die Sicherheit.Round trips may have security implications. Beispielsweise kann das Deserialisieren und Speichern von großen Mengen externer Daten ein Sicherheitsrisiko darstellen.For example, deserializing and storing large amounts of extraneous data may be a security risk. Es kann Sicherheitsbedenken in Bezug auf die erneute Ausgabe dieser Daten geben, weil sich diese nicht verifizieren lassen, insbesondere wenn sie digital signiert sind.There may be security concerns about re-emitting this data that there is no way to verify, especially if digital signatures are involved. Beispielsweise könnte im obigen Szenario der Endpunkt mit Version&#160;1 einen Nickname -Wert signieren, der bösartige Daten enthält.For example, in the previous scenario, the version 1 endpoint could be signing a Nickname value that contains malicious data. Schließlich kann es Bedenken hinsichtlich der Schemavalidierung geben: Es kann wünschenswert sein, dass ein Endpunkt nur Daten, die genau dem angegebenen Datenvertrag entsprechen, und keine zusätzlichen Werte ausgibt.Finally, there may be schema validity concerns: an endpoint may want to always emit data that strictly adheres to its stated contract and not any extra values. Im vorigen Beispiel besagt der Datenvertrag des Endpunkts mit Version&#160;1, dass dieser nur Name und PhoneNumberausgibt, und bei Verwendung einer Schemavalidierung verursacht die Ausgabe des zusätzlichen Nickname -Werts einen Fehler.In the previous example, the version 1 endpoint’s contract says that it emits only Name and PhoneNumber, and if schema validation is being used, emitting the extra Nickname value causes validation to fail.

Aktivieren und Deaktivieren von RoundtripsEnabling and Disabling Round Trips

Wenn Sie Roundtrips deaktivieren möchten, implementieren Sie die IExtensibleDataObject -Schnittstelle nicht.To turn off round trips, do not implement the IExtensibleDataObject interface. Falls Sie keine Kontrolle über die Typen haben, legen Sie den ignoreExtensionDataObject -Parameter auf true fest, um Roundtrips zu unterbinden.If you have no control over the types, set the ignoreExtensionDataObject parameter to true to achieve the same effect.

ObjektdiagrammbeibehaltungObject Graph Preservation

Normalerweise befasst sich das Serialisierungsprogramm nicht mit der Objektidentität, wie im folgenden Code gezeigt.Normally, the serializer does not care about object identity, as in the following code.

[DataContract]
public class PurchaseOrder
{
    [DataMember]
    public Address billTo;
    [DataMember]
    public Address shipTo;
}

[DataContract]
public class Address
{
    [DataMember]
    public string street;
}
<DataContract()>  _
Public Class PurchaseOrder

    <DataMember()>  _
    Public billTo As Address

    <DataMember()>  _
    Public shipTo As Address

End Class 

<DataContract()>  _
Public Class Address

    <DataMember()>  _
    Public street As String

End Class 

Im folgenden Code wird ein PurchaseOrder-Objekt erstellt.The following code creates a purchase order.

// Construct a purchase order:
Address adr = new Address();
adr.street = "123 Main St.";
PurchaseOrder po = new PurchaseOrder();
po.billTo = adr;
po.shipTo = adr;
' Construct a purchase order:
Dim adr As New Address()
adr.street = "123 Main St."
Dim po As New PurchaseOrder()
po.billTo = adr
po.shipTo = adr

Beachten Sie, dass das billTo -Feld und shipTo -Feld auf die gleiche Objektinstanz festgelegt werden.Notice that billTo and shipTo fields are set to the same object instance. Das generierte XML dupliziert allerdings die doppelt vorhandenen Informationen und ähnelt dem folgenden XML.However, the generated XML duplicates the information duplicated, and looks similar to the following XML.

<PurchaseOrder>  
  <billTo><street>123 Main St.</street></billTo>  
  <shipTo><street>123 Main St.</street></shipTo>  
</PurchaseOrder>  

Dieser Ansatz verfügt über die folgenden Eigenschaften, die möglicherweise unerwünscht sind:However, this approach has the following characteristics, which may be undesirable:

  • Leistung.Performance. Die Datenreplizierung ist ineffizient.Replicating data is inefficient.

  • Zirkuläre Verweise.Circular references. Wenn Objekte auf sich selbst verweisen, resultiert die Serialisierung durch Replizierung auch dann in einer Endlosschleife, wenn die Verweise über andere Objekte führen.If objects refer to themselves, even through other objects, serializing by replication results in an infinite loop. (Das Serialisierungsprogramm löst in diesem Fall eine SerializationException aus.)(The serializer throws a SerializationException if this happens.)

  • Semantik.Semantics. Gelegentlich ist es wichtig, die Tatsache zu vermerken, dass zwei Verweise auf das gleiche Objekt und nicht auf zwei identische Objekte zeigen.Sometimes it is important to preserve the fact that two references are to the same object, and not to two identical objects.

Aus diesem Grund verfügen einige DataContractSerializer -Konstruktorüberladungen über den preserveObjectReferences -Parameter (dessen Standardwert lautet false).For these reasons, some DataContractSerializer constructor overloads have a preserveObjectReferences parameter (the default is false). Wenn dieser Parameter auf truefestgelegt wird, wird eine spezielle Methode zur Codierung von Objektreferenzen verwendet, die lediglich WCFWCF versteht.When this parameter is set to true, a special method of encoding object references, which only WCFWCF understands, is used. Wenn der Parameter auf truefestgelegt wird, sieht das XML-Codebeispiel etwa wie folgt aus.When set to true, the XML code example now resembles the following.

<PurchaseOrder ser:id="1">  
  <billTo ser:id="2"><street ser:id="3">123 Main St.</street></billTo>  
  <shipTo ser:ref="2"/>  
</PurchaseOrder>  

Der Namespace "ser" verweist auf den Standardserialisierungsnamespace http://schemas.microsoft.com/2003/10/Serialization/.The "ser" namespace refers to the standard serialization namespace, http://schemas.microsoft.com/2003/10/Serialization/. Jedes Datenelement wird nur einmal serialisiert und erhält eine ID-Nummer. Bei nachfolgender Verwendung wird ein Verweis auf die bereits serialisierten Daten erzeugt.Each piece of data is serialized only once and given an ID number, and subsequent uses result in a reference to the already serialized data.

Wichtig

Ist sowohl das Attribut "id" als auch das Attribut "ref" im XMLElementdes Datenvertrags vorhanden, wird das Attribut "ref" berücksichtigt, und das Attribut "id" wird ignoriert.If both "id" and "ref" attributes are present in the data contract XMLElement, then the "ref" attribute is honored and the "id" attribute is ignored.

Es ist wichtig, die Einschränkungen dieses Modus zu kennen:It is important to understand the limitations of this mode:

  • Das XML, das der DataContractSerializer erzeugt, wenn der preserveObjectReferences -Parameter auf true festgelegt ist, kann von keiner anderen Technologie verarbeitet werden. Nur eine andere DataContractSerializer -Instanz, bei der der preserveObjectReferences -Parameter auch auf truefestgelegt ist, kann darauf zugreifen.The XML the DataContractSerializer produces with preserveObjectReferences set to true is not interoperable with any other technologies, and can be accessed only by another DataContractSerializer instance, also with preserveObjectReferences set to true.

  • Es ist keine Metadaten- (Schema)-Unterstützung für diese Funktion verfügbar.There is no metadata (schema) support for this feature. Das Schema, das erzeugt wird, ist nur in dem Fall gültig, in dem preserveObjectReferences auf falsefestgelegt ist.The schema that is produced is valid only for the case when preserveObjectReferences is set to false.

  • Diese Funktion bewirkt möglicherweise, dass Serialisierung und Deserialisierung langsamer ausgeführt werden.This feature may cause the serialization and deserialization process to run slower. Obwohl die Daten nicht repliziert werden müssen, müssen in diesem Modus zusätzliche Objektvergleiche angestellt werden.Although data does not have to be replicated, extra object comparisons must be performed in this mode.

Achtung

Wenn der preserveObjectReferences -Modus aktiviert ist, muss der maxItemsInObjectGraph -Wert unbedingt auf das richtige Kontingent festgelegt werden.When the preserveObjectReferences mode is enabled, it is especially important to set the maxItemsInObjectGraph value to the correct quota. Aufgrund der Art und Weise, wie Arrays in diesem Modus behandelt werden, ist es für Angreifer einfach, eine kleine bösartige Nachricht zu erstellen, die in zu einem hohen Speicherverbrauch führt, der nur durch das maxItemsInObjectGraph -Kontingent begrenzt wird.Due to the way arrays are handled in this mode, it is easy for an attacker to construct a small malicious message that results in large memory consumption limited only by the maxItemsInObjectGraph quota.

Angeben eines Datenvertrag-ErsatzzeichensSpecifying a Data Contract Surrogate

Einige DataContractSerializer -Konstruktorüberladungen verfügen über den dataContractSurrogate -Parameter, der möglicherweise auf nullfestgelegt ist.Some DataContractSerializer constructor overloads have a dataContractSurrogate parameter, which may be set to null. Andernfalls können Sie mit diesem Parameter ein Datenvertrag-Ersatzzeichenfestlegen, d.&#160;h. einen Typ, der die IDataContractSurrogate -Schnittstelle implementiert.Otherwise, you can use it to specify a data contract surrogate, which is a type that implements the IDataContractSurrogate interface. Sie können dann mithilfe dieser Schnittstelle die Serialisierung und Deserialisierung anpassen.You can then use the interface to customize the serialization and deserialization process. Weitere Informationen finden Sie unterFor more information, seeDatenvertrag-Ersatzzeichen. Data Contract Surrogates.

SerialisierungSerialization

Die folgenden Ausführungen gelten für alle von XmlObjectSerializerabgeleiteten Klassen, einschließlich der DataContractSerializer -Klasse und der NetDataContractSerializer -Klasse.The following information applies to any class that inherits from the XmlObjectSerializer, including the DataContractSerializer and NetDataContractSerializer classes.

Einfache SerialisierungSimple Serialization

Die grundlegendste Möglichkeit, ein Objekt zu serialisieren, besteht darin, es der WriteObject -Methode zu übergeben.The most basic way to serialize an object is to pass it to the WriteObject method. Es gibt drei Überladungen, jeweils eine zum Schreiben in ein Stream-Objekt, ein XmlWriter-Objekt oder ein XmlDictionaryWriter-Objekt.There are three overloads, one each for writing to a Stream, an XmlWriter, or an XmlDictionaryWriter. Bei Verwendung der Stream -Überladung enthält die Ausgabe XML in UTF-8-Codierung.With the Stream overload, the output is XML in the UTF-8 encoding. Bei Verwendung der XmlDictionaryWriter -Überladung optimiert das Serialisierungsprogramm seine Ausgabe für binäres XML.With the XmlDictionaryWriter overload, the serializer optimizes its output for binary XML.

Bei Verwendung der WriteObject Methode, die das Serialisierungsprogramm den Standardnamen und -Namespace verwendet, für das Wrapperelement und gibt es zusammen mit dem Inhalt (siehe Abschnitt "Angeben der Standardeinstellung Stamm Name und Namespace" oben).When using the WriteObject method, the serializer uses the default name and namespace for the wrapper element and writes it out along with the contents (see the previous "Specifying the Default Root Name and Namespace" section).

Im folgenden Codebeispiel wird der Schreibvorgang mit XmlDictionaryWriterveranschaulicht.The following example demonstrates writing with an XmlDictionaryWriter.

Person p = new Person();
DataContractSerializer dcs =
    new DataContractSerializer(typeof(Person));
XmlDictionaryWriter xdw =
    XmlDictionaryWriter.CreateTextWriter(someStream,Encoding.UTF8 );
dcs.WriteObject(xdw, p);
Dim p As New Person()
Dim dcs As New DataContractSerializer(GetType(Person))
Dim xdw As XmlDictionaryWriter = _
    XmlDictionaryWriter.CreateTextWriter(someStream, Encoding.UTF8)
dcs.WriteObject(xdw, p)

Damit wird XML generiert, das etwa wie folgt aussieht.This produces XML similar to the following.

<Person>  
  <Name>Jay Hamlin</Name>  
  <Address>123 Main St.</Address>  
</Person>  

Schrittweise SerialisierungStep-By-Step Serialization

Verwenden Sie die Methoden WriteStartObject, WriteObjectContentund WriteEndObject , um das Endelement und den Inhalt des Objekts zu schreiben bzw. das Wrapperelement zu schließen.Use the WriteStartObject, WriteObjectContent, and WriteEndObject methods to write the end element, write the object contents, and close the wrapper element, respectively.

Hinweis

Es sind keine Stream -Überladungen für diese Methoden verfügbar.There are no Stream overloads of these methods.

Diese schrittweise Serialisierung wird üblicherweise in zwei Fällen eingesetzt.This step-by-step serialization has two common uses. Erstens wird sie verwendet, um Inhalte wie Attribute oder Kommentare zwischen WriteStartObject und WriteObjectContenteinzufügen. Dies wird im folgenden Beispiel veranschaulicht.One is to insert contents such as attributes or comments between WriteStartObject and WriteObjectContent, as shown in the following example.

dcs.WriteStartObject(xdw, p);
xdw.WriteAttributeString("serializedBy", "myCode");
dcs.WriteObjectContent(xdw, p);
dcs.WriteEndObject(xdw);
dcs.WriteStartObject(xdw, p)
xdw.WriteAttributeString("serializedBy", "myCode")
dcs.WriteObjectContent(xdw, p)
dcs.WriteEndObject(xdw)

Damit wird XML generiert, das etwa wie folgt aussieht.This produces XML similar to the following.

<Person serializedBy="myCode">  
  <Name>Jay Hamlin</Name>  
  <Address>123 Main St.</Address>  
</Person>  

Sie wird auch häufig verwendet, um die Verwendung von WriteStartObject und WriteEndObject zu vermeiden und ein eigenes, benutzerdefiniertes Wrapperelement zu schreiben (oder die Erstellung eines Wrapperelements ganz zu umgehen), wie im folgenden Code gezeigt.Another common use is to avoid using WriteStartObject and WriteEndObject entirely, and to write your own custom wrapper element (or even skip writing a wrapper altogether), as shown in the following code.

xdw.WriteStartElement("MyCustomWrapper");
dcs.WriteObjectContent(xdw, p);
xdw.WriteEndElement();
xdw.WriteStartElement("MyCustomWrapper")
dcs.WriteObjectContent(xdw, p)
xdw.WriteEndElement()

Damit wird XML generiert, das etwa wie folgt aussieht.This produces XML similar to the following.

<MyCustomWrapper>  
  <Name>Jay Hamlin</Name>  
  <Address>123 Main St.</Address>  
</MyCustomWrapper>  

Hinweis

Die Verwendung der schrittweisen Serialisierung kann in XML resultieren, das keinem gültigen Schema entspricht.Using step-by-step serialization may result in schema-invalid XML.

DeserialisierungDeserialization

Die folgenden Ausführungen gelten für alle von XmlObjectSerializer abgeleiteten Klassen, einschließlich der DataContractSerializer-Klasse und der NetDataContractSerializer-Klasse.The following information applies to any class that inherits from the XmlObjectSerializer, including the DataContractSerializer and NetDataContractSerializer classes.

Die grundlegendste Möglichkeit, ein Objekt zu deserialisieren, besteht im Aufruf einer der Überladungen der ReadObject -Methode.The most basic way to deserialize an object is to call one of the ReadObject method overloads. Es sind drei Überladungen verfügbar, jeweils eine zum Lesen mit einem XmlDictionaryReader-Objekt, einem XmlReader-Objekt oder einem Stream-Objekt.There are three overloads, one each for reading with a XmlDictionaryReader, an XmlReader, or a Stream. Beachten Sie, dass die Stream -Überladung einen textbasierten XmlDictionaryReader erstellt, der nicht durch Kontingente geschützt wird und nur zum Lesen vertrauenswürdiger Daten verwendet werden sollte.Note that the Stream overload creates a textual XmlDictionaryReader that is not protected by any quotas, and should be used only to read trusted data.

Beachten Sie außerdem, dass das von der ReadObject -Methode zurückgegebene Objekt in den entsprechenden Typ umgewandelt werden muss.Also note that the object the ReadObject method returns must be cast to the appropriate type.

Im folgenden Code wird eine Instanz der DataContractSerializer -Klasse und ein XmlDictionaryReadererzeugt, und dann eine Person -Instanz deserialisiert.The following code constructs an instance of the DataContractSerializer and an XmlDictionaryReader, then deserializes a Person instance.

DataContractSerializer dcs = new DataContractSerializer(typeof(Person));
FileStream fs = new FileStream(path, FileMode.Open);
XmlDictionaryReader reader =
XmlDictionaryReader.CreateTextReader(fs, new XmlDictionaryReaderQuotas());

Person p = (Person)dcs.ReadObject(reader);
Dim dcs As New DataContractSerializer(GetType(Person))
Dim fs As New FileStream(path, FileMode.Open)
Dim reader As XmlDictionaryReader = _
   XmlDictionaryReader.CreateTextReader(fs, New XmlDictionaryReaderQuotas())

Dim p As Person = CType(dcs.ReadObject(reader), Person)

Positionieren Sie den XML-Reader vor dem Aufruf der ReadObject -Methode auf dem Wrapperelement oder einem Knoten, der keinen Inhalt enthält und sich vor dem Wrapperelement befindet.Before calling the ReadObject method, position the XML reader on the wrapper element or on a non-content node that precedes the wrapper element. Sie können zu diesem Zweck die Read -Methode der XmlReader -Klasse oder der davon abgeleiteten Klasse aufrufen und den NodeTypetesten, wie im folgenden Code gezeigt.You can do this by calling the Read method of the XmlReader or its derivation, and testing the NodeType, as shown in the following code.

DataContractSerializer ser = new DataContractSerializer(typeof(Person),
"Customer", @"http://www.contoso.com");
FileStream fs = new FileStream(path, FileMode.Open);
XmlDictionaryReader reader =
XmlDictionaryReader.CreateTextReader(fs, new XmlDictionaryReaderQuotas());
while (reader.Read())
{
    switch (reader.NodeType)
    {
        case XmlNodeType.Element:
            if (ser.IsStartObject(reader))
            {
                Console.WriteLine("Found the element");
                Person p = (Person)ser.ReadObject(reader);
                Console.WriteLine("{0} {1}    id:{2}",
                    p.Name , p.Address);
            }
            Console.WriteLine(reader.Name);
            break;
    }
}
Dim ser As New DataContractSerializer(GetType(Person), "Customer", "http://www.contoso.com")
Dim fs As New FileStream(path, FileMode.Open)
Dim reader As XmlDictionaryReader = XmlDictionaryReader.CreateTextReader(fs, New XmlDictionaryReaderQuotas())

While reader.Read()
    Select Case reader.NodeType
        Case XmlNodeType.Element
            If ser.IsStartObject(reader) Then
                Console.WriteLine("Found the element")
                Dim p As Person = CType(ser.ReadObject(reader), Person)
                Console.WriteLine("{0} {1}", _
                                   p.Name, p.Address)
            End If
            Console.WriteLine(reader.Name)
    End Select
End While

Beachten Sie, dass Sie Attribute dieses Wrapperelements lesen können, bevor der Reader an ReadObjectübergeben wird.Note that you can read attributes on this wrapper element before handing the reader to ReadObject.

Bei Verwendung einer einfachen ReadObject Überladungen verfügbar, das Deserialisierungsprogramm sucht der Standardname und Namespace auf dem Wrapperelement (Siehe vorhergehenden Abschnitt "Angeben der Standardeinstellung Stamm Name und Namespace") und löst eine Ausnahme aus, wenn er einen unbekannten findet Element.When using one of the simple ReadObject overloads, the deserializer looks for the default name and namespace on the wrapper element (see the preceding section, "Specifying the Default Root Name and Namespace") and throws an exception if it finds an unknown element. Im vorstehenden Beispiel wird das Wrapperelement <Person> erwartet.In the preceding example, the <Person> wrapper element is expected. Die IsStartObject -Methode wird aufgerufen, um zu überprüfen, ob der Reader auf einem Element mit dem erwarteten Namen positioniert wurde.The IsStartObject method is called to verify that the reader is positioned on an element that is named as expected.

Es gibt eine Möglichkeit, diese Namensüberprüfung des Wrapperelements zu deaktivieren. Einige Überladungen der ReadObject -Methode akzeptieren den Booleschen Parameter verifyObjectName, der standardmäßig auf true festgelegt ist.There is a way to disable this wrapper element name check; some overloads of the ReadObject method take the Boolean parameter verifyObjectName, which is set to true by default. Wenn der Parameter auf falsefestgelegt wird, werden Name und Namespace des Wrapperelements ignoriert.When set to false, the name and namespace of the wrapper element is ignored. Dies ist beim Lesen von XML hilfreich, das mit dem oben beschriebenen schrittweisen Serialisierungsmechanismus geschrieben wurde.This is useful for reading XML that was written using the step-by-step serialization mechanism described previously.

Verwenden von NetDataContractSerializerUsing the NetDataContractSerializer

Der Hauptunterschied zwischen der DataContractSerializer -Klasse und der NetDataContractSerializer -Klasse besteht darin, dass die Klasse DataContractSerializer mit Datenvertragsnamen arbeitet, während die NetDataContractSerializer -Klasse vollständige .NET Framework.NET Framework -Assemblynamen und Typnamen in das serialisierte XML ausgibt.The primary difference between the DataContractSerializer and the NetDataContractSerializer is that the DataContractSerializer uses data contract names, whereas the NetDataContractSerializer outputs full .NET Framework.NET Framework assembly and type names in the serialized XML. Dies bedeutet, dass die Endpunkte für Serialisierung und Deserialisierung genau die gleichen Datentypen verwenden müssen.This means that the exact same types must be shared between the serialization and deserialization endpoints. Folglich muss der Mechanismus der bekannten Typen nicht in Verbindung mit NetDataContractSerializer verwendet werden, weil stets bekannt ist, welche Typen im Einzelnen deserialisiert werden müssen.This means that the known types mechanism is not required with the NetDataContractSerializer because the exact types to be deserialized are always known.

Es können jedoch verschiedene Probleme auftreten:However, several problems can occur:

  • Sicherheit.Security. Jeder Typ, der in dem zu deserialisierenden XML gefunden wird, wird geladen.Any type found in the XML being deserialized is loaded. Dies kann ausgenutzt werden, um das Laden bösartiger Typen zu erzwingen.This can be exploited to force the loading of malicious types. NetDataContractSerializer sollte nur dann für nicht vertrauenswürdige Daten eingesetzt werden, wenn ein Serialisierungsbinder verwendet wird (über die Binder -Eigenschaft oder einen Konstruktorparameter).Using the NetDataContractSerializer with untrusted data should be done only if a Serialization Binder is used (using the Binder property or constructor parameter). Die Binder lässt nur das Laden sicherer Typen zu.The binder permits only safe types to be loaded. Der Bindermechanismus ist mit dem Mechanismus identisch, den die im System.Runtime.Serialization -Namespace definierten Typen verwenden.The Binder mechanism is identical to the one that types in the System.Runtime.Serialization namespace use.

  • Versionskontrolle.Versioning. Die Angabe vollständiger Typ- und Assemblynamen im XML schränkt die Verfahren zur Versionskontrolle der Typen schwerwiegend ein.Using full type and assembly names in the XML severely restricts how types can be versioned. Folgendes kann nicht geändert werden: Typnamen, Namespaces, Assemblynamen und Assemblyversionen.The following cannot be changed: type names, namespaces, assembly names, and assembly versions. Wenn die AssemblyFormat -Eigenschaft oder der Konstruktorparameter auf Simple statt den Standardwert Full festgelegt wird, sind Änderungen der Assemblyversion, jedoch keine generischen Parametertypen zulässig.Setting the AssemblyFormat property or constructor parameter to Simple instead of the default value of Full allows for assembly version changes, but not for generic parameter types.

  • Interoperabilität.Interoperability. Weil die Typ- und Assemblynamen aus .NET Framework.NET Framework in das XML aufgenommen werden, können andere Plattformen als .NET Framework.NET Framework nicht auf die resultierenden Daten zugreifen.Because .NET Framework.NET Framework type and assembly names are included in the XML, platforms other than the .NET Framework.NET Framework cannot access the resulting data.

  • Leistung.Performance. Die Ausgabe von Typ- und Assemblynamen vergrößert den Umfang des resultierenden XML bedeutend.Writing out the type and assembly names significantly increases the size of the resulting XML.

Dieser Mechanismus ähnelt der binären Serialisierung bzw. der SOAP-Serialisierung, die von .NET Framework.NET Framework -Remoting verwendet wird (insbesondere von BinaryFormatter und SoapFormatter).This mechanism is similar to binary or SOAP serialization used by .NET Framework.NET Framework remoting (specifically, the BinaryFormatter and the SoapFormatter).

Die Verwendung von NetDataContractSerializer unterscheidet sich von der Verwendung von DataContractSerializerlediglich in folgender Hinsicht:Using the NetDataContractSerializer is similar to using the DataContractSerializer, with the following differences:

  • Die Konstruktoren erfordern keine Angabe des Stammtyps.The constructors do not require you to specify a root type. Sie können jeden Typ mit der gleichen Instanz von NetDataContractSerializerserialisieren.You can serialize any type with the same instance of the NetDataContractSerializer.

  • Die Konstruktoren akzeptieren keine Liste bekannter Typen an.The constructors do not accept a list of known types. Der Mechanismus der bekannten Typen ist unnötig, wenn die Typnamen in XML serialisiert werden.The known types mechanism is unnecessary if type names are serialized into the XML.

  • Die Konstruktoren akzeptieren kein Datenvertrag-Ersatzzeichen.The constructors do not accept a data contract surrogate. Stattdessen akzeptieren sie einen ISurrogateSelector -Parameter namens surrogateSelector (welcher der SurrogateSelector -Eigenschaft zugeordnet wird).Instead, they accept an ISurrogateSelector parameter called surrogateSelector (which maps to the SurrogateSelector property). Dies ist ein älterer Ersatzzeichenmechanismus.This is a legacy surrogate mechanism.

  • Die Konstruktoren akzeptieren einen Parameter namens assemblyFormat vom FormatterAssemblyStyle , welcher der AssemblyFormat -Eigenschaft zugeordnet wird.The constructors accept a parameter called assemblyFormat of the FormatterAssemblyStyle that maps to the AssemblyFormat property. Wie oben erläutert, lassen sich damit die Versionskontrollfähigkeiten des Serialisierungsprogramms verbessern.As discussed previously, this can be used to enhance the versioning capabilities of the serializer. Dies entspricht dem FormatterAssemblyStyle -Mechanismus in der binären Serialisierung oder der SOAP-Serialisierung.This is identical to the FormatterAssemblyStyle mechanism in binary or SOAP serialization.

  • Die Konstruktoren akzeptieren einen StreamingContext -Parameter namens context , welcher der Context -Eigenschaft zugeordnet wird.The constructors accept a StreamingContext parameter called context that maps to the Context property. Sie können diesen zur Übergabe von Informationen an Typen nutzen, die serialisiert werden.You can use this to pass information into types being serialized. Diese Art der Verwendung entspricht dem StreamingContext -Mechanismus, der in anderen System.Runtime.Serialization -Klassen verwendet wird.This usage is identical to that of the StreamingContext mechanism used in other System.Runtime.Serialization classes.

  • Die Serialize -Methode und die Deserialize -Methode sind Aliase für die WriteObject -Methode bzw. die ReadObject -Methode.The Serialize and Deserialize methods are aliases for the WriteObject and ReadObject methods. Sie sollen ein konsistenteres Programmiermodell für die binäre Serialisierung oder SOAP-Serialisierung bereitstellen.These exist to provide a more consistent programming model with binary or SOAP serialization.

Weitere Informationen finden Sie unterFor more information aboutDiese Funktionen finden Sie unter Binärserialisierung. these features, see Binary Serialization.

Die von der NetDataContractSerializer -Klasse und der DataContractSerializer -Klasse verwendeten XML-Formate sind normalerweise nicht kompatibel.The XML formats that the NetDataContractSerializer and the DataContractSerializer use are normally not compatible. Das heißt, es ist nicht möglich, Daten mit einem dieser Serialisierungsprogramme zu serialisieren und sie mit dem anderen Serialisierungsprogramm zu deserialisieren.That is, attempting to serialize with one of these serializers and deserialize with the other is not a supported scenario.

Beachten Sie außerdem, dass NetDataContractSerializer nicht den vollständigen .NET Framework.NET Framework -Typnamen und Assemblynamen für jeden Knoten im Objektdiagramm ausgibt.Also, note that the NetDataContractSerializer does not output the full .NET Framework.NET Framework type and assembly name for each node in the object graph. Diese Informationen werden nur im Fall möglicher Mehrdeutigkeiten ausgegeben.It outputs that information only where it is ambiguous. Das heißt, sie werden auf der Stammobjektebene und für polymorphe Fälle ausgegeben.That is, it outputs at the root object level and for any polymorphic cases.

Siehe auchSee Also

DataContractSerializer
NetDataContractSerializer
XmlObjectSerializer
Binäre SerialisierungBinary Serialization
Vom Datenvertragsserialisierer unterstützte TypenTypes Supported by the Data Contract Serializer