Verwenden der XmlSerializer-KlasseUsing the XmlSerializer Class

Windows Communication Foundation (WCF)Windows Communication Foundation (WCF) kann zwei verschiedene Serialisierungstechnologien verwenden, um die Daten in der Anwendung in XML für die Übertragung zwischen Clients und Diensten umzuwandeln; dieser Vorgang wird als Serialisierung bezeichnet. can use two different serialization technologies to turn the data in your application into XML that is transmitted between clients and services, a process called serialization.

DataContractSerializer als StandardDataContractSerializer as the Default

Standardmäßig verwendet WCFWCF die DataContractSerializer-Klasse, um Datentypen zu serialisieren.By default WCFWCF uses the DataContractSerializer class to serialize data types. Dieses Serialisierungsprogramm unterstützt die folgenden Typen:This serializer supports the following types:

  • Primitive Typen (z. B. ganze Zahlen, Zeichenfolgen und Bytearrays) sowie einige spezielle Typen wie XmlElement und DateTime, die als Primitive behandelt werden.Primitive types (for example, integers, strings, and byte arrays), as well as some special types, such as XmlElement and DateTime, which are treated as primitives.

  • Datenvertragstypen (mit dem DataContractAttribute-Attribut markierte Typen).Data contract types (types marked with the DataContractAttribute attribute).

  • Mit dem SerializableAttribute-Attribut markierte Typen, einschließlich Typen, die die ISerializable-Schnittstelle implementieren.Types marked with the SerializableAttribute attribute, which include types that implement the ISerializable interface.

  • Typen, die die IXmlSerializable-Schnittstelle implementieren.Types that implement the IXmlSerializable interface.

  • Viele allgemeine Auflistungstypen, einschließlich vieler generischer Auflistungstypen.Many common collection types, which include many generic collection types.

Viele .NET Framework.NET Framework-Typen fallen in die letzten beiden Kategorien und sind daher serialisierbar.Many .NET Framework.NET Framework types fall into the latter two categories and are thus serializable. Arrays serialisierbarer Typen sind ebenfalls serialisierbar.Arrays of serializable types are also serializable. Eine vollständige Liste finden Sie unter angeben von Datenübertragung in Dienstverträgen.For a complete list, see Specifying Data Transfer in Service Contracts.

Das DataContractSerializer, zusammen mit Datenvertragstypen verwendet, ist die empfohlene Methode, um neue WCFWCF-Dienste zu schreiben.The DataContractSerializer, used together with data contract types, is the recommended way to write new WCFWCF services. Weitere Informationen finden Sie unterFor more information, seeVerwenden von Datenverträgen. Using Data Contracts.

Verwendung der XmlSerializer-KlasseWhen to Use the XmlSerializer Class

WCFWCF unterstützt auch die XmlSerializer-Klasse. also supports the XmlSerializer class. Die XmlSerializer-Klasse ist nicht exklusiv in WCFWCF verfügbar.The XmlSerializer class is not unique to WCFWCF. Vielmehr handelt es sich hierbei um das gleiche Serialisierungsmodul, das auch von den ASP.NETASP.NET-Webdiensten verwendet wird.It is the same serialization engine that ASP.NETASP.NET Web services use. Die XmlSerializer-Klasse unterstützt deutlich weniger Typen als die DataContractSerializer-Klasse, ermöglicht jedoch eine größere Kontrolle über das resultierende XML und unterstützt den XSD-Schemastandard (XML Schema definition language) stärker.The XmlSerializer class supports a much narrower set of types than the DataContractSerializer class, but allows much more control over the resulting XML and supports much more of the XML Schema definition language (XSD) standard. Sie erfordert außerdem keine deklarativen Attribute für die serialisierbaren Typen.It also does not require any declarative attributes on the serializable types. Weitere Informationen finden Sie unterFor more information, see dem Thema zur XML-Serialisierung in der .NET Framework.NET Framework-Dokumentation. the XML Serialization topic in the .NET Framework.NET Framework documentation. Die XmlSerializer-Klasse unterstützt keine Datenvertragstypen.The XmlSerializer class does not support data contract types.

Bei Verwendung von Svcutil.exe oder Hinzufügen eines Dienstverweises Funktion Visual StudioVisual Studio zum Generieren von Clientcode für einen Dienst eines Drittanbieters oder auf ein Schema eines Drittanbieters zugreifen, wird ein geeignetes Serialisierungsprogramm automatisch für Sie ausgewählt.When using Svcutil.exe or the Add Service Reference feature in Visual StudioVisual Studio to generate client code for a third-party service, or to access a third-party schema, an appropriate serializer is automatically selected for you. Wenn das Schema nicht mit DataContractSerializer kompatibel ist, wird XmlSerializer ausgewählt.If the schema is not compatible with the DataContractSerializer, the XmlSerializer is selected.

Manuelles Wechseln zu XmlSerializerManually Switching to the XmlSerializer

Es kann vorkommen, dass Sie manuell zu XmlSerializer wechseln müssen.At times, you may have to manually switch to the XmlSerializer. Dies ist beispielsweise in den folgenden Situationen der Fall:This happens, for example, in the following cases:

  • Beim Migrieren einer Anwendung von ASP.NETASP.NET-Webdiensten zu WCFWCF kann es sinnvoll sein, vorhandene XmlSerializer-kompatible Typen erneut zu verwenden, anstatt neue Datenvertragstypen zu erstellen.When migrating an application from ASP.NETASP.NET Web services to WCFWCF, you may want to reuse existing, XmlSerializer-compatible types instead of creating new data contract types.

  • Wenn die präzise Steuerung von in Nachrichten enthaltenen XML-Daten wichtig ist, jedoch kein WSDL (Web Services Description Language)-Dokument zur Verfügung steht, 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.When precise control over the XML that appears in messages is important, but a Web Services Description Language (WSDL) document is not available, for example, when creating a service with types that have to comply to a certain standardized, published schema that is not compatible with the DataContractSerializer.

  • Beim Erstellen von Diensten, die dem älteren SOAP-Codierungsstandard folgen.When creating services that follow the legacy SOAP Encoding standard.

In diesen und anderen Fällen können Sie manuell zur XmlSerializer-Klasse wechseln, indem Sie das XmlSerializerFormatAttribute-Attribut auf den Dienst anwenden, wie im folgenden Code dargestellt.In these and other cases, you can manually switch to the XmlSerializer class by applying the XmlSerializerFormatAttribute attribute to your service, as shown in the following code.

   [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überlegungenSecurity Considerations

Hinweis

Beim Wechseln von Serialisierungsmodulen ist große Sorgfalt geboten.It is important to be careful when switching serialization engines. Derselbe Typ kann je nach verwendetem Serialisierungsprogramm mehrere Serialisierungskonzepte umfassen.The same type can serialize to XML differently depending on the serializer being used. Wenn Sie versehentlich das falsche Serialisierungsprogramm verwenden, legen Sie möglicherweise Informationen aus dem Typ offen, deren Offenlegung Sie nicht beabsichtigt haben.If you accidentally use the wrong serializer, you might be disclosing information from the type that you did not intend to disclose.

Beispielsweise serialisiert die DataContractSerializer-Klasse beim Serialisieren von Datenvertragstypen nur mit dem DataMemberAttribute-Attribut markierte Member.For example, the DataContractSerializer class only serializes members marked with the DataMemberAttribute attribute when serializing data contract types. Die XmlSerializer-Klasse serialisiert jeden öffentlichen Member.The XmlSerializer class serializes any public member. Beachten Sie den Typ im folgenden Code:See the type in the following code.

[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 der creditCardNumber-Member serialisiert, was wahrscheinlich nicht beabsichtigt ist.If the type is inadvertently used in a service contract where the XmlSerializer class is selected, the creditCardNumber member is serialized, which is probably not intended.

Auch wenn 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.Even though the DataContractSerializer class is the default, you can explicitly select it for your service (although doing this should never be required) by applying the DataContractFormatAttribute attribute to the service contract type.

Das für den Dienst verwendete Serialisierungsprogramm ist ein wesentlicher Bestandteil des Vertrags und kann durch Auswahl einer anderen Bindung oder durch Ändern anderer Konfigurationseinstellungen nicht geändert werden.The serializer used for the service is an integral part of the contract and cannot be changed by selecting a different binding or by changing other configuration settings.

Andere wichtige Sicherheitsüberlegungen gelten für die XmlSerializer-Klasse.Other important security considerations apply to the XmlSerializer class. Es wird zuerst dringend empfohlen, dass jede WCFWCF-Anwendung, die die XmlSerializer-Klasse verwendet, mit einem vor Offenlegung geschützten Schlüssel signiert ist.First, it is strongly recommended that any WCFWCF application that uses the XmlSerializer class is signed with a key that is safeguarded from disclosure. Diese Empfehlung gilt sowohl für das manuelle Wechseln zu XmlSerializer als auch ein automatisches Wechseln (mit Svcutil.exe, "Dienstverweis hinzufügen" oder ein ähnliches Tool).This recommendation applies both when a manual switch to the XmlSerializer is performed and when an automatic switch is performed (by Svcutil.exe, Add Service Reference, or a similar tool). Grund hierfür ist die XmlSerializer Serialisierungsmodul unterstützt das Laden von vorgenerierten Serialisierungsassemblys solange sie mit demselben Schlüssel wie die Anwendung signiert sind.This is because the XmlSerializer serialization engine supports the loading of pre-generated serialization assemblies as long as they are signed with the same key as the application. Eine nicht signierte Anwendung ist vollständig ungeschützt gegen die Möglichkeit, dass eine bösartige Assembly, die mit dem erwarteten Namen der vorgenerierten Serialisierungsassembly übereinstimmt, im Anwendungsordner oder im globalen Assemblycache platziert wird.An unsigned application is completely unprotected from the possibility of a malicious assembly matching the expected name of the pre-generated serialization assembly being placed in the application folder or the global assembly cache. Natürlich muss ein Angreifer zuerst Schreibzugriff auf einen der beiden Speicherorte erhalten, um diese Aktion auszuführen.Of course, an attacker must first gain write access to one of these two locations to attempt this action.

Eine weitere Bedrohung, die beim Verwenden von XmlSerializer vorhanden ist, hängt mit dem Schreibzugriff auf den temporären Ordners des Systems zusammen.Another threat that exists whenever you use XmlSerializer is related to write access to the system temporary folder. Die XmlSerializer Serialisierungsmodul erstellt und verwendet temporäre Serialisierungsassemblys in diesem Ordner.The XmlSerializer serialization engine creates and uses temporary serialization assemblies in this folder. Sie sollten sich der Tatsache bewusst sein, dass jeder Vorgang mit Schreibzugriff auf den temporären Ordner diese Serialisierungsassemblys mit bösartigem Code überschreiben kann.You should be aware that any process with write access to the temporary folder may overwrite these serialization assemblies with malicious code.

Regeln für XmlSerializer-UnterstützungRules for XmlSerializer support

Sie können mit XmlSerializer kompatible Attribute nicht direkt auf Vertragsvorgangsparameter oder Rückgabewerte anwenden.You cannot directly apply XmlSerializer-compatible attributes to contract operation parameters or return values. Sie können jedoch auf typisierte Nachrichten (Nachrichtenvertragstextteile) angewendet werden, wie der folgende Code zeigt:However, they can be applied to typed messages (message contract body parts), as shown in the following code.

[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 

Beim Anwenden auf typisierte Nachrichtenmember überschreiben diese Attribute Eigenschaften, die mit den typisierten Nachrichtenattributen in Konflikt stehen.When applied to typed message members, these attributes override properties that conflict on the typed message attributes. Beispielsweise wird im folgenden Code ElementName durch Name überschrieben.For example, in the following code, ElementName overrides 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 

Das MessageHeaderArrayAttribute-Attribut wird nicht unterstützt, wenn XmlSerializer verwendet wird.The MessageHeaderArrayAttribute attribute is not supported when using the XmlSerializer.

Hinweis

In diesem Fall löst XmlSerializer die folgende Ausnahme aus, die vor WCFWCF freigegeben wird: "Für ein auf oberster Schemaebene deklariertes Element darf nicht maxOccurs > 1 gelten.In this case, the XmlSerializer throws the following exception, which is released prior to WCFWCF: "An element declared at the top level of a schema cannot have maxOccurs > 1. Geben Sie ein Wrapperelement für "more" an, indem Sie XmlArray oder XmlArrayItem anstelle von XmlElementAttribute verwenden oder indem Sie den Wrapped-Parameterstil verwenden.Provide a wrapper element for 'more' by using XmlArray or XmlArrayItem instead of XmlElementAttribute, or by using the Wrapped parameter style."

Wenn Sie eine solche Ausnahme empfangen, prüfen Sie, ob diese Situation zutrifft.If you receive such an exception, investigate whether this situation applies.

WCFWCF unterstützt das SoapIncludeAttribute- und das XmlIncludeAttribute-Attribut in Nachrichtenverträgen und Vorgangsverträgen nicht; verwenden Sie stattdessen das KnownTypeAttribute-Attribut. does not support the SoapIncludeAttribute and XmlIncludeAttribute attributes in message contracts and operation contracts; use the KnownTypeAttribute attribute instead.

Typen, die die IXmlSerializable-Schnittstelle implementierenTypes that Implement the IXmlSerializable Interface

Typen, die die IXmlSerializable-Schnittstelle implementieren, werden von DataContractSerializer vollständig unterstützt.Types that implement the IXmlSerializable interface are fully supported by the DataContractSerializer. Sie sollten das XmlSchemaProviderAttribute-Attribut immer auf diese Typen anwenden, um das dazugehörige Schema zu steuern.The XmlSchemaProviderAttribute attribute should always be applied to these types to control their schema.

Warnung

Wenn Sie polymorphe Typen verwenden, müssen Sie XmlSchemaProviderAttribute auf den Typ anwenden, um sicherzustellen, dass der richtige Typ serialisiert wird.If you are serializing polymorphic types you must apply the XmlSchemaProviderAttribute to the type to ensure the correct type is serialized.

Es gibt drei Varianten von Typen, die IXmlSerializable implementieren: Typen, die beliebigen Inhalt darstellen, Typen, die ein einzelnes Element darstellen, und ältere DataSet-Typen.There are three varieties of types that implement IXmlSerializable: types that represent arbitrary content, types that represent a single element, and legacy DataSet types.

  • Inhaltstypen verwenden eine vom XmlSchemaProviderAttribute-Attribut angegebene Schemaanbietermethode.Content types use a schema provider method specified by the XmlSchemaProviderAttribute attribute. Die Methode gibt nicht null zurück, und die IsAny-Eigenschaft des Attributs wird auf ihrem Standardwert false belassen.The method does not return null and the IsAny property on the attribute is left at its default value of false. Dies ist die häufigste Verwendung von IXmlSerializable-Typen.This is the most common usage of IXmlSerializable types.

  • Elementtypen werden verwendet, wenn ein IXmlSerializable-Typ seinen eigenen Stammelementnamen kontrollieren muss.Element types are used when an IXmlSerializable type must control its own root element name. Um einen Typ als Elementtyp zu kennzeichnen, legen Sie entweder die IsAny-Eigenschaft des XmlSchemaProviderAttribute-Attributs auf true fest, oder geben Sie über die Schemaanbietermethode null zurück.To mark a type as an element type, either set the IsAny property on the XmlSchemaProviderAttribute attribute to true or return null from the schema provider method. Die Verwendung einer Schemaanbietermethode ist für Elementtypen optional. Sie können unter null anstatt des Methodennamens auch XmlSchemaProviderAttribute angeben.Having a schema provider method is optional for element types – you may specify null instead of the method name in the XmlSchemaProviderAttribute. Wenn IsAny jedoch true ist und eine Schemaanbietermethode angegeben ist, muss die Methode null zurückgeben.However, if IsAny is true and a schema provider method is specified, the method must return null.

  • Bei älteren DataSet-Typen handelt es sich um IXmlSerializable-Typen, die nicht mit dem XmlSchemaProviderAttribute-Attribut gekennzeichnet sind.Legacy DataSet types are IXmlSerializable types that are not marked with the XmlSchemaProviderAttribute attribute. Stattdessen verwenden sie zur Schemagenerierung die GetSchema-Methode.Instead, they rely on the GetSchema method for schema generation. Dieses Muster wird für den DataSet-Typ und seine von ihm abgeleiteten typisierten Dataset-Klassen in älteren Versionen von .NET Framework verwendet. Es ist jedoch veraltet und wird nur aus Legacygründen noch unterstützt.This pattern is used for the DataSet type and its typed dataset derives a class in earlier versions of the .NET Framework, but is now obsolete and is supported only for legacy reasons. Verlassen Sie sich nicht auf dieses Muster, und wenden Sie immer das XmlSchemaProviderAttribute auf Ihre IXmlSerializable-Typen an.Do not rely on this pattern and always apply the XmlSchemaProviderAttribute to your IXmlSerializable types.

IXmlSerializable-InhaltstypenIXmlSerializable Content Types

Wenn Sie einen Datenmember eines Typs serialisieren, der IXmlSerializable implementiert und ein wie zuvor definierter Inhaltstyp ist, schreibt das Serialisierungsprogramm das Wrapperelement für den Datenmember und übergibt die Steuerung an die WriteXml-Methode.When serializing a data member of a type that implements IXmlSerializable and is a content type as defined previously, the serializer writes the wrapper element for the data member and passes control to the WriteXml method. Die WriteXml-Implementierung kann beliebige XML-Daten schreiben, auch zum Hinzufügen der Attribute zum Wrapperelement.The WriteXml implementation can write any XML, which includes adding attributes to the wrapper element. Nachdem WriteXml abgeschlossen ist, schließt das Serialisierungsprogramm das Element.After WriteXml is done, the serializer closes the 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.When deserializing a data member of a type that implements IXmlSerializable and is a content type as defined previously, the deserializer positions the XML reader on the wrapper element for the data member and passes control to the ReadXml method. Die Methode muss das ganze Element lesen, einschließlich des Start- und Endtags.The method must read the entire element, including the start and end tags. Stellen Sie sicher, dass der ReadXml-Code auch den Fall verarbeitet, in dem das Element leer ist.Make sure your ReadXml code handles the case where the element is empty. Außerdem sollte sich Ihre ReadXml-Implementierung nicht darauf verlassen, dass das Wrapperelement einen bestimmten Namen aufweist.Additionally, your ReadXml implementation should not rely on the wrapper element being named a particular way. Der Name wird vom Serialisierungsprogramm ausgewählt und kann variieren.The name is chosen by the serializer can vary.

Es ist zulässig, IXmlSerializable-Inhaltstypen polymorph zuzuweisen, zum Beispiel zu Datenmembern vom Typ Object.It is permitted to assign IXmlSerializable content types polymorphically, for example, to data members of type Object. Es ist auch zulässig, dass die Typinstanzen NULL sind.It is also permitted for the type instances to be null. Außerdem ist es möglich, IXmlSerializable-Typen bei aktivierter Objektdiagrammbeibehaltung und mit NetDataContractSerializer zu verwenden.Finally, it is possible to use IXmlSerializable types with object graph preservation enabled and with the NetDataContractSerializer. Diese Features erfordern es, dass das WCFWCF-Serialisierungsprogramm bestimmte Attribute in das Wrapperelement einfügt ("nil" und "type" im XML-Schemainstanznamespace und "Id", "Ref", "Type" und "Assembly" in einem WCFWCF-spezifischen Namespace).All these features require the WCFWCF serializer to attach certain attributes into the wrapper element ("nil" and "type" in the XML Schema Instance namespace and "Id", "Ref", "Type" and "Assembly" in a WCFWCF-specific namespace).

Bei der Implementierung von ReadXml zu ignorierende AttributeAttributes to Ignore when Implementing ReadXml

Bevor die Steuerung an Ihren ReadXml-Code übergeben wird, untersucht das Deserialisierungsprogramm das XML-Element, erkennt diese speziellen XML-Attribute und führt die erforderlichen Aktionen aus.Before passing control to your ReadXml code, the deserializer examines the XML element, detects these special XML attributes, and acts on them. Wenn "nil" zum Beispiel true ist, wird ein Nullwert deserialisiert, und ReadXml wird nicht aufgerufen.For example, if "nil" is true, a null value is deserialized and ReadXml is not called. Falls Polymorphie erkannt wird, wird der Inhalt des Elements deserialisiert, als ob es sich um einen anderen Typ handeln würde.If polymorphism is detected, the contents of the element are deserialized as if it was a different type. Die ReadXml-Implementierung des polymorph zugewiesenen Typs wird aufgerufen.The polymorphically-assigned type’s implementation of ReadXml is called. Eine ReadXml-Implementierung sollte diese speziellen Attribute auf jeden Fall ignorieren, da sie vom Deserialisierungsprogramm verarbeitet werden.In any case, a ReadXml implementation should ignore these special attributes because they are handled by the deserializer.

Schemaüberlegungen für IXmlSerializable-InhaltstypenSchema Considerations for IXmlSerializable Content Types

Beim Exportieren eines Schemas und eines IXmlSerializable-Inhaltstyp wird die Schemaanbietermethode aufgerufen.When exporting schema and an IXmlSerializable content type, the schema provider method is called. Ein XmlSchemaSet wird an die Schemaanbietermethode übergeben.An XmlSchemaSet is passed to the schema provider method. Die Methode kann dem Schemasatz gültige Schemas hinzufügen.The method can add any valid schema to the schema set. Der Schemasatz enthält das Schema, das zum Zeitpunkt des Schemaexports bereits bekannt ist.The schema set contains the schema that is already known at the time when schema export occurs. Wenn die Schemaanbietermethode dem Schemasatz ein Element hinzufügen muss, muss sie ermitteln, ob ein XmlSchema mit dem geeigneten Namespace im Satz bereits vorhanden ist.When the schema provider method must add an item to the schema set, it must determine whether an XmlSchema with the appropriate namespace already exists in the set. Falls dies der Fall ist, muss die Schemaanbietermethode das neue Element dem vorhandenen XmlSchema hinzufügen.If it does, the schema provider method must add the new item to the existing XmlSchema. Andernfalls muss sie eine neue XmlSchema-Instanz erstellen.Otherwise, it must create a new XmlSchema instance. Dies ist wichtig, wenn Arrays mit IXmlSerializable-Typen verwendet werden.This is important if arrays of IXmlSerializable types are being used. Wenn Sie zum Beispiel über einen IXmlSerializable-Typ verfügen, der als Typ "A" in Namespace "B" exportiert wird, ist es möglich, dass der Schemasatz beim Aufrufen der Schemaanbietermethode das Schema "B" bereits enthält, um den Typ "ArrayOfA" aufzunehmen.For example, if you have an IXmlSerializable type that gets exported as type "A" in namespace "B", it is possible that by the time the schema provider method is called the schema set already contains the schema for "B" to hold the "ArrayOfA" type.

Zusätzlich zum Hinzufügen von Typen zum XmlSchemaSet muss die Schemaanbietermethode für Inhaltstypen einen anderen Wert als NULL zurückgeben.In addition to adding types to the XmlSchemaSet, the schema provider method for content types must return a non-null value. Sie kann ein XmlQualifiedName-Element zurückgeben, das den Namen des Schematyps angibt, der für den jeweiligen IXmlSerializable-Typ verwendet wird.It can return an XmlQualifiedName that specifies the name of the schema type to use for the given IXmlSerializable type. Dieser qualifizierte Name dient auch als Datenvertragsname und Namespace für den Typ.This qualified name also serves as the data contract name and namespace for the type. Es ist zulässig, einen Typ zurückzugeben, der nicht im Schemasatz vorhanden ist, wenn dies direkt nach der Rückgabe der Schemaanbietermethode erfolgt.It is permitted to return a type that does not exist in the schema set immediately when the schema provider method returns. 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.However, it is expected that by the time all related types are exported (the Export method is called for all relevant types on the XsdDataContractExporter and the Schemas property is accessed), the type exists in the schema set. Das Zugreifen auf die Schemas-Eigenschaft, bevor alle relevanten Export-Aufrufe durchgeführt wurden, kann zu einer XmlSchemaException führen.Accessing the Schemas property before all relevant Export calls have been made can result in an XmlSchemaException. Weitere Informationen finden Sie unterFor more information aboutDer Exportvorgang finden Sie unter Exportieren von Schemas aus Klassen. the export process, see Exporting Schemas from Classes.

Die Schemaanbietermethode kann auch den zu verwendenden XmlSchemaType zurückgeben.The schema provider method can also return the XmlSchemaType to use. Der Typ kann anonym oder nicht anonym sein.The type may or may not be anonymous. Wenn er anonym ist, wird das Schema für den IXmlSerializable-Typ jeweils als anonymer Typ exportiert, wenn der IXmlSerializable-Typ als Datenmember verwendet wird.If it is anonymous, the schema for the IXmlSerializable type is exported as an anonymous type every time the IXmlSerializable type is used as a data member. Der IXmlSerializable-Typ verfügt trotzdem noch über einen Datenvertragsnamen und einen Namespace.The IXmlSerializable type still has a data contract name and namespace. (Dies wird bestimmt, wie in beschrieben Datenvertragsnamen mit dem Unterschied, dass die DataContractAttribute Attribut kann nicht zum Anpassen des Namens verwendet werden.) Wenn er nicht anonym ist, muss es sich um einen der Typen im XmlSchemaSet handeln.(This is determined as described in Data Contract Names except that the DataContractAttribute attribute cannot be used to customize the name.) If it is not anonymous, it must be one of the types in the XmlSchemaSet. Dies entspricht dem Zurückgeben von XmlQualifiedName für den Typ.This case is equivalent to returning the XmlQualifiedName of the type.

Zusätzlich wird für den Typ eine globale Elementdeklaration exportiert.Additionally, a global element declaration is exported for the type. Wenn auf den Typ nicht das XmlRootAttribute-Attribut angewendet wurde, weist das Element denselben Namen und Namespace wie der Datenvertrag auf, und seine nillable-Eigenschaft ist true.If the type does not have the XmlRootAttribute attribute applied to it, the element has the same name and namespace as the data contract, and its "nillable" property is true. Die einzige Ausnahme dabei ist der Schemanamespace ("http://www.w3.org/2001/XMLSchema"). Wenn der Datenvertrag des Typs in diesem Namespace enthalten ist, befindet sich das entsprechende globale Element im leeren Namespace, da es nicht zulässig ist, dem Schemanamespace neue Elemente hinzuzufügen.The only exception to this is the schema namespace ("http://www.w3.org/2001/XMLSchema") – if the type’s data contract is in this namespace, the corresponding global element is in the blank namespace because it is forbidden to add new elements to the schema namespace. Wenn auf den Typ das XmlRootAttribute-Attribut angewendet wurde, wird die globale Elementdeklaration exportiert, indem Folgendes verwendet wird: die Eigenschaften ElementName, Namespace und IsNullable.If the type has the XmlRootAttribute attribute applied to it, the global element declaration is exported using the following: ElementName, Namespace and IsNullable properties. Die bei angewendetem XmlRootAttribute geltenden Standardeinstellungen sind der Datenvertragsname, ein leerer Namespace und der Wert true für "nillable".The defaults with XmlRootAttribute applied are the data contract name, a blank namespace and "nillable" being true.

Die gleichen Regeln für die globale Elementdeklaration gelten für Legacy-Datasettypen.The same global element declaration rules apply to legacy dataset types. Beachten Sie, dass das XmlRootAttribute keine globalen Elementdeklarationen überschreiben kann, die mithilfe von benutzerdefiniertem Code hinzugefügt wurden. Diese können mithilfe der Schemaanbietermethode dem XmlSchemaSet oder über GetSchema für Legacy-Datasettypen hinzugefügt worden sein.Note that the XmlRootAttribute cannot override global element declarations added through custom code, either added to the XmlSchemaSet using the schema provider method or through GetSchema for legacy dataset types.

IXmlSerializable-ElementtypenIXmlSerializable Element Types

Für IXmlSerializable-Elementtypen ist entweder die IsAny-Eigenschaft auf true festgelegt, oder ihre Schemaanbietermethode gibt null zurück.IXmlSerializable element types have either the IsAny property set to true or have their schema provider method return null.

Das Serialisieren und Deserialisieren eines Elementtyps ähnelt stark dem Serialisieren und Deserialisieren eines Inhaltstyps.Serializing and deserializing an element type is very similar to serializing and deserializing a content type. Es gibt jedoch einige wichtige Unterschiede:However, there are some important differences:

  • Von der WriteXml-Implementierung wird erwartet, dass sie genau ein Element schreibt (das natürlich mehrere untergeordnete Elemente enthalten kann).The WriteXml implementation is expected to write exactly one element (which could of course contain multiple child elements). Sie sollte keine Attribute außerhalb dieses einzelnen Elements, mehrerer gleichgeordneter Elemente oder gemischten Inhalts schreiben.It should not be writing attributes outside of this single element, multiple sibling elements or mixed content. Das Element ist ggf. leer.The element may be empty.

  • Die ReadXml-Implementierung sollte das Wrapperelement nicht lesen.The ReadXml implementation should not read the wrapper element. Es wird erwartet, dass sie das einzelne Element liest, das von WriteXml erzeugt wird.It is expected to read the one element that WriteXml produces.

  • Wenn das Serialisierungsprogramm regelmäßig einen Elementtyp serialisiert (zum Beispiel als Datenmember in einem Datenvertrag), gibt das Serialisierungsprogramm ein Wrapperelement aus, bevor WriteXml aufgerufen wird. Dies entspricht der Vorgehensweise bei Inhaltstypen.When serializing an element type regularly (for example, as a data member in a data contract), the serializer outputs a wrapper element before calling WriteXml, as with content types. Bei der Serialisierung eines Elementtyps auf der obersten Ebene gibt das Serialisierungsprogramm normalerweise jedoch kein Wrapperelement für das Element aus, das WriteXml schreibt. Dies ist nur der Fall, wenn beim Erstellen des Serialisierungsprogramms in den Konstruktoren DataContractSerializer oder NetDataContractSerializer explizit ein Stammname und ein Namespace angegeben werden.However, when serializing an element type at the top level, the serializer does not normally output a wrapper element at all around the element that WriteXml writes, unless a root name and namespace are explicitly specified when constructing the serializer in the DataContractSerializer or NetDataContractSerializer constructors. Weitere Informationen finden Sie unterFor more information, seeSerialisierung und Deserialisierung. Serialization and Deserialization.

  • Beim Serialisieren eines Elementtyps auf der obersten Ebene, ohne zur Entwurfszeit den Stammnamen und einen Namespace anzugeben, führen WriteStartObject und WriteEndObject im Wesentlichen keine Aktionen aus, und WriteObjectContent ruft einfach WriteXml auf.When serializing an element type at the top level without specifying the root name and namespace at construction time, WriteStartObject and WriteEndObject essentially do nothing and WriteObjectContent calls WriteXml. In diesem Modus kann das Objekt, das serialisiert wird, nicht null sein und nicht polymorph zugewiesen werden.In this mode, the object being serialized cannot be null and cannot be polymorphically assigned. Außerdem kann die Objektdiagrammbeibehaltung nicht aktiviert und NetDataContractSerializer kann nicht verwendet werden.Also, object graph preservation cannot enabled and the NetDataContractSerializer cannot be used.

  • Beim Deserialisieren eines Elementtyps auf der obersten Ebene, ohne zur Entwurfszeit den Stammnamen und den Namespace anzugeben, gibt IsStartObject den Wert true zurück, wenn der Anfang eines beliebigen Elements gefunden werden kann.When deserializing an element type at the top level without specifying the root name and namespace at construction time, IsStartObject returns true if it can find the start of any element. ReadObject mit auf verifyObjectName festgelegtem true-Parameter verhält sich genau so wie IsStartObject, bevor das Objekt gelesen wird.ReadObject with the verifyObjectName parameter set to true behaves in the same way as IsStartObject before actually reading the object. ReadObject übergibt das Steuerelement dann an die ReadXml-Methode.ReadObject then passes control to ReadXml method.

Das Schema, das für die Elementtypen exportiert wird, entspricht dem Schema für den XmlElement-Typ, wie in einem Abschnitt weiter oben beschrieben. Es gilt jedoch die Ausnahme, dass die Schemaanbietermethode wie bei Inhaltstypen dem XmlSchemaSet zusätzliche Schemas hinzufügen kann.The schema exported for element types is the same as for the XmlElement type as described in an earlier section, except that the schema provider method can add any additional schema to the XmlSchemaSet as with content types. Das Verwenden des XmlRootAttribute-Attributs mit Elementtypen ist nicht zulässig, und globale Elementdeklarationen werden für diese Typen nicht ausgegeben.Using the XmlRootAttribute attribute with element types is not allowed, and global element declarations are never emitted for these types.

Unterschiede zu XmlSerializerDifferences from the XmlSerializer

Die IXmlSerializable-Schnittstelle und das XmlSchemaProviderAttribute- und XmlRootAttribute-Attribut werden vom XmlSerializer auch verstanden.The IXmlSerializable interface and the XmlSchemaProviderAttribute and XmlRootAttribute attributes are also understood by the XmlSerializer . Aber es gibt einige Unterschiede dabei, wie diese Elemente im Datenvertragsmodell behandelt werden.However, there are some differences in how these are treated in the data contract model. Die wichtigsten Unterschiede werden im Folgenden zusammengefasst:The important differences are summarized in the following list:

  • Die Schemaanbietermethode muss öffentlich sein, um im XmlSerializer verwendet werden zu können. Sie muss jedoch nicht öffentlich sein, um im Datenvertragsmodell verwendet werden zu können.The schema provider method must be public to be used in the XmlSerializer, but does not have to be public to be used in the data contract model.

  • Die Schemaanbietermethode wird aufgerufen, wenn für IsAny im Datenvertragsmodell true gilt, jedoch nicht für den XmlSerializer.The schema provider method is called when IsAny is true in the data contract model but not with the XmlSerializer.

  • Wenn das XmlRootAttribute-Attribut für Inhalts- oder Legacy-Datasettypen nicht vorhanden ist, exportiert der XmlSerializer eine globale Elementdeklaration in den leeren Namespace.When the XmlRootAttribute attribute is not present for content or legacy dataset types, the XmlSerializer exports a global element declaration in the blank namespace. Im Datenvertragsmodell ist der verwendete Namespace normalerweise der Datenvertragsnamespace, wie bereits beschrieben.In the data contract model, the namespace used is normally the data contract namespace as described earlier.

Beachten Sie diese Unterschiede, wenn Sie Typen erstellen, die mit beiden Serialisierungstechnologien verwendet werden.Be aware of these differences when creating types that are used with both serialization technologies.

Importieren von IXmlSerializable-SchemasImporting IXmlSerializable Schema

Beim Importieren eines Schemas, das aus IXmlSerializable-Typen generiert wurde, gibt es verschiedene Möglichkeiten:When importing a schema generated from IXmlSerializable types, there are a few possibilities:

  • Dem generierten Schema kann ein gültiges datenvertragsschema handeln, wie in beschrieben Datenvertrags-Schemareferenz.The generated schema may be a valid data contract schema as described in Data Contract Schema Reference. In diesem Fall kann das Schema auf die übliche Weise importiert werden, und es werden normale Datenvertragstypen generiert.In this case, schema can be imported as usual and regular data contract types are generated.

  • Bei dem generierten Schema kann es sich auch um ein nicht gültiges Datenvertragsschema handeln.The generated schema may not be a valid data contract schema. Ihre Schemaanbietermethode kann zum Beispiel Schemas mit XML-Attributen generieren, die im Datenvertragsmodell nicht unterstützt werden.For example, your schema provider method may generate schema that involves XML attributes that are not supported in the data contract model. In diesem Fall können Sie das Schema als IXmlSerializable-Typen importieren.In this case, you can import the schema as IXmlSerializable types. Dieser Modus "Import" ist nicht standardmäßig aktiviert, jedoch kann problemlos mit aktiviert werden – z. B. die /importXmlTypes Befehlszeilenoption, um die ServiceModel Metadata Utility Tool (Svcutil.exe).This import mode is not on by default but can easily be enabled – for example, with the /importXmlTypes command-line switch to the ServiceModel Metadata Utility Tool (Svcutil.exe). Dies wird ausführlich beschrieben unter der Importieren von Schemas zum Generieren von Klassen.This is described in detail in the Importing Schema to Generate Classes. Beachten Sie, dass Sie für die Typinstanzen direkt mit den XML-Daten arbeiten müssen.Note that you must work directly with the XML for your type instances. Sie können auch erwägen, eine andere Serialisierungstechnologie zu verwenden, die einen größeren Schemabereich unterstützt. Weitere Informationen finden Sie im Thema zur Verwendung von XmlSerializer.You may also consider using a different serialization technology that supports a wider range of schema – see the topic on using the XmlSerializer.

  • Es ist ratsam, Ihre vorhandenen IXmlSerializable-Typen im Proxy wiederzuverwenden, anstatt neue zu generieren.You may want to reuse your existing IXmlSerializable types in the proxy instead of generating new ones. In diesem Fall können Sie die Funktion mit den referenzierten Typen verwenden, die im Thema zum Importieren von Schemas zum Generieren von Typen beschrieben ist, um den wiederzuverwendenden Typ anzugeben.In this case, the referenced types feature described in the Importing Schema to Generate Types topic can be used to indicate the type to reuse. Dies entspricht dem Verwenden der /reference Schalters von svcutil.exe, der die Assembly angibt, die die wiederzuverwendenden Typen enthält.This corresponds to using the /reference switch on svcutil.exe, which specifies the assembly that contains the types to reuse.

XmlSerializer-LegacyverhaltenXmlSerializer Legacy Behavior

In .NET Framework 4.0 und früher wurden von XmlSerializer temporäre Serialisierungsassemblys generiert, indem C#-Code in eine Datei geschrieben wurde.In the .NET Framework 4.0 and earlier, the XmlSerializer generated temporary serialization assemblies by writing C# code to a file. Die Datei wurde anschließend in eine Assembly kompiliert.The file was then compiled into an assembly. Dieses Verhalten hatte einige unerwünschte Folgen, z. B. das Verzögern der Startzeit für die Serialisierung.This behavior had some undesirable consequences like slowing the startup time for the serializer. In .NET Framework 4.5 wurde das Verhalten geändert, um die Assemblys zu generieren, ohne den Compiler verwenden zu müssen.In .NET Framework 4.5, this behavior was changed to generate the assemblies without requiring use of the compiler. Einige Entwickler möchten den generierten C#-Code jedoch anzeigen.Some developers may wish to see the generated C# code. Sie können mit der folgenden Konfiguration festlegen, dass dieses Legacyverhalten verwendet wird:You can specify to use this legacy behavior by the following configuration:

<?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, z. B. auftreten der XmlSerializer zum Serialisieren von einer abgeleiteten Klasse mit einem nicht öffentlichen neue Außerkraftsetzungswert fehlschlägt, können Sie zurück zum Wechseln der XMLSerializer Legacyverhalten mithilfe der folgenden Konfigurations:If you run into compatibility issues, such as the XmlSerializer failing to serialize a derived class with a non-public new override, you can switch back to the XMLSerializer legacy behavior by using the following configuration:

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

Als Alternative zu den oben beschriebenen Konfiguration können Sie die folgende Konfiguration auf einem Computer unter .NET Framework 4.5 oder höher:As an alternative to the above configuration, you can use the following configuration on a machine running .NET Framework 4.5 or later version:

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

Hinweis

Die <xmlSerializer useLegacySerializerGeneration="true"/> Switch funktioniert nur auf einem Computer unter .NET Framework 4.5 oder höher.The <xmlSerializer useLegacySerializerGeneration="true"/> switch only works on a machine running .NET Framework 4.5 or later version. Die oben genannten appSettings Ansatz funktioniert für alle .NET Framework-Versionen.The above appSettings approach works on all .NET Framework versions.

Siehe auchSee Also

DataContractFormatAttribute
DataContractSerializer
XmlSerializer
MessageHeaderArrayAttribute
Angeben von Datenübertragung in DienstverträgenSpecifying Data Transfer in Service Contracts
Verwenden von DatenverträgenUsing Data Contracts
Vorgehensweise: Verbessern der Startzeit von WCF-Clientanwendungen mit dem XmlSerializerHow to: Improve the Startup Time of WCF Client Applications using the XmlSerializer