Teilen über


XML- und ADO.NET typen in Datenverträgen

Das Windows Communication Foundation (WCF)-Datenvertragsmodell unterstützt bestimmte Typen, die XML direkt darstellen. Wenn diese Typen in XML serialisiert werden, schreibt der Serialisierer den XML-Inhalt dieser Typen ohne weitere Verarbeitung aus. Unterstützte Typen sind XmlElement, Arrays von XmlNode (aber nicht der XmlNode Typ selbst) sowie Typen, die IXmlSerializable implementieren. Die DataSet und DataTable Typen sowie typisierte Datensätze werden häufig in der Datenbankprogrammierung verwendet. Diese Typen implementieren die IXmlSerializable Schnittstelle und sind daher im Datenvertragsmodell serialisierbar. Einige besondere Aspekte für diese Typen werden am Ende dieses Themas aufgeführt.

XML-Typen

Xml-Element

Der XmlElement Typ wird mithilfe des XML-Inhalts serialisiert. Verwenden Sie z. B. den folgenden Typ.

[DataContract(Namespace=@"http://schemas.contoso.com")]
public class MyDataContract
{
    [DataMember]
    public XmlElement myDataMember;
    public void TestClass()
    {
        XmlDocument xd = new XmlDocument();
        myDataMember = xd.CreateElement("myElement");
        myDataMember.InnerText = "myContents";
        myDataMember.SetAttribute
         ("myAttribute","myValue");
    }
}
<DataContract([Namespace]:="http://schemas.contoso.com")> _
Public Class MyDataContract
    <DataMember()> _
    Public myDataMember As XmlElement

    Public Sub TestClass()
        Dim xd As New XmlDocument()
        myDataMember = xd.CreateElement("myElement")
        myDataMember.InnerText = "myContents"
        myDataMember.SetAttribute("myAttribute", "myValue")

    End Sub
End Class

Dies wird wie folgt in XML serialisiert:

<MyDataContract xmlns="http://schemas.contoso.com">  
    <myDataMember>  
        <myElement xmlns="" myAttribute="myValue">  
            myContents  
        </myElement>  
    </myDataMember>  
</MyDataContract>  

Beachten Sie, dass ein Wrapper-Datenmitgliedselement <myDataMember> weiterhin vorhanden ist. Es gibt keine Möglichkeit, dieses Element im Datenvertragsmodell zu entfernen. Die Serialisierer, die dieses Modell behandeln (das DataContractSerializer und das NetDataContractSerializer), können spezielle Attribute in dieses Wrapperelement ausgeben. Zu diesen Attributen gehören das standardmäßige "nil"-Attribut der XML-Schema-Instanz (das es erlaubt, dass XmlElement zu null wird) und das "type"-Attribut (das die polymorphe Verwendung von XmlElement ermöglicht). Außerdem sind die folgenden XML-Attribute spezifisch für WCF: "ID", "Ref", "Type" und "Assembly". Diese Attribute können ausgegeben werden, um die Verwendung des XmlElement bei aktiviertem Objektdiagramm-Erhaltungsmodus zu unterstützen oder mit dem NetDataContractSerializer. (Weitere Informationen zum Erhaltungsmodus des Objektdiagramms finden Sie unter Serialisierung und Deserialisierung.)

Arrays oder Auflistungen von XmlElement sind zulässig und werden wie jede andere Array oder Auflistung behandelt. Das heißt, es gibt ein Wrapperelement für die gesamte Auflistung und ein separates Wrapperelement (ähnlich <myDataMember> wie im vorherigen Beispiel) für jedes XmlElement element im Array.

Bei der Deserialisierung wird eine XmlElement vom Deserialisierer aus dem eingehenden XML-Code erstellt. Ein gültiges übergeordnetes XmlDocument wird vom Deserialisierungsprogramm bereitgestellt.

Stellen Sie sicher, dass das XML-Fragment, das für ein XmlElement Deserialisiert ist, alle von ihr verwendeten Präfixe definiert und nicht auf Präfixdefinitionen aus vorgängern Elementen basiert. Dies ist nur von Bedeutung, wenn Sie DataContractSerializer verwenden, um auf XML von einer anderen Quelle (als DataContractSerializer) zuzugreifen.

Bei Verwendung mit dem DataContractSerializer kann die XmlElement polymorph zugewiesen werden, jedoch nur einem Datenmitglied des Typs Object. Auch wenn es IEnumerable implementiert, kann ein XmlElement nicht als Sammlungstyp verwendet und keinem IEnumerable Datenmitglied zugeordnet werden. Wie bei allen polymorphen Zuordnungen gibt der DataContractSerializer den Datenvertragsnamen im resultierenden XML-Code aus. In diesem Fall ist es "XmlElement" im http://schemas.datacontract.org/2004/07/System.Xml Namespace.

Mit der NetDataContractSerializer, wird jede gültige polymorphe Zuordnung von XmlElement (zu Object oder IEnumerable) unterstützt.

Versuchen Sie nicht, eines der Serialisierungsprogramme mit Typen zu verwenden, die von XmlElement abgeleitet sind, unabhängig davon, ob sie polymorph zugewiesen werden oder nicht.

XmlNode-Array

Die Verwendung von Arrays von XmlNode ist der Verwendung von XmlElement sehr ähnlich. Die Verwendung von XmlNode Arrays bietet Ihnen mehr Flexibilität als die Verwendung XmlElement. Sie können innerhalb des Datenmember-Wrapperelements mehrere Elemente schreiben. Sie können auch andere Inhalte als Elemente innerhalb des Datenelementumbruchelements einfügen, z. B. XML-Kommentare. Schließlich können Sie Attribute in das umschließende Datenelement einfügen. All dies kann durch Befüllen des Arrays XmlNode mit bestimmten abgeleiteten Klassen von XmlNode wie XmlAttribute, XmlElement oder XmlComment erreicht werden. Verwenden Sie z. B. den folgenden Typ.

[DataContract(Namespace="http://schemas.contoso.com")]
public class MyDataContract
{
    [DataMember]
    public XmlNode[] myDataMember = new XmlNode[4];
    public void TestClass()
    {
        XmlDocument xd = new XmlDocument();
        XmlElement xe = xd.CreateElement("myElement");
        xe.InnerText = "myContents";
        xe.SetAttribute
         ("myAttribute","myValue");
    
        XmlAttribute atr = xe.Attributes[0];
        XmlComment cmnt = xd.CreateComment("myComment");
        
      myDataMember[0] = atr;
      myDataMember[1] = cmnt;
      myDataMember[2] = xe;
      myDataMember[3] = xe;
    }
}
<DataContract([Namespace]:="http://schemas.contoso.com")> _
Public Class MyDataContract
    <DataMember()> _
    Public myDataMember(3) As XmlNode

    Public Sub TestClass()
        Dim xd As New XmlDocument()
        Dim xe As XmlElement = xd.CreateElement("myElement")
        xe.InnerText = "myContents"
        xe.SetAttribute("myAttribute", "myValue")

        Dim atr As XmlAttribute = xe.Attributes(0)
        Dim cmnt As XmlComment = xd.CreateComment("myComment")

        myDataMember(0) = atr
        myDataMember(1) = cmnt
        myDataMember(2) = xe
        myDataMember(3) = xe

    End Sub

End Class

Bei der Serialisierung ähnelt der resultierende XML-Code dem folgenden Code.

<MyDataContract xmlns="http://schemas.contoso.com">  
  <myDataMember myAttribute="myValue">  
     <!--myComment-->  
     <myElement xmlns="" myAttribute="myValue">  
 myContents  
     </myElement>  
     <myElement xmlns="" myAttribute="myValue">  
       myContents  
     </myElement>  
  </myDataMember>  
</MyDataContract>  

Beachten Sie, dass das Datenelementwrapperelement <myDataMember> ein Attribut, einen Kommentar und zwei Elemente enthält. Dies sind die vier XmlNode Instanzen, die serialisiert wurden.

Ein Array von XmlNode, das zu ungültigem XML führt, kann nicht serialisiert werden. Ein Beispiel wäre ein Array aus zwei XmlNode Instanzen, von denen die erste eine XmlElement und die zweite eine XmlAttribute ist. Dies ist ungültig, da diese Sequenz keiner gültigen XML-Instanz entspricht (es gibt keine Möglichkeit, das Attribut anzufügen).

Bei der Deserialisierung eines Arrays von XmlNodewerden Knoten erstellt und mit Informationen aus dem eingehenden XML-Code aufgefüllt. Ein gültiges übergeordnetes XmlDocument wird vom Deserialisierungsprogramm bereitgestellt. Alle Knoten werden deserialisiert. Dazu zählen auch alle Attribute im Datenmember-Wrapperelement, aber nicht die Attribute, die von den WCF-Serialisierungsmodulen dort platziert wurden (z. B. die Attribute, die zum Angeben der polymorphen Zuweisung verwendet werden). Der Vorbehalt, alle Namespacepräfixe im XML-Fragment zu definieren, gilt für die Deserialisierung von Arrays von XmlNode ebenso wie bei der Deserialisierung von XmlElement.

Wenn die Serialisierer mit aktivierter Objektdiagramm-Erhaltung verwendet werden, wird die Objektgleichstellung nur auf der Ebene von XmlNode Arrays und nicht auf einzelnen XmlNode Instanzen beibehalten.

Versuchen Sie nicht, ein Array zu serialisieren, bei dem einer oder mehrere der Knoten auf XmlNode gesetzt ist. Es ist zulässig, dass das gesamte Array null ist, nicht jedoch ein einzelner XmlNode im Array. Wenn das gesamte Arraymemm null ist, enthält das Wrapperdatenelementelement ein spezielles Attribut, das angibt, dass es null ist. Bei der Deserialisierung wird auch das gesamte Arrayelement null.

Nur normale Arrays XmlNode werden speziell vom Serialisierer behandelt. Als andere Sammlungstypen deklarierte Datenmitglieder, die XmlNode enthalten, oder Datenmitglieder, die als Arrays von Typen deklariert sind, die von XmlNode abgeleitet sind, werden nicht speziell behandelt. Daher sind sie normalerweise nicht serialisierbar, es sei denn, sie erfüllen auch eines der anderen Kriterien für die Serialisierung.

Arrays oder Auflistungen von Arrays von XmlNode sind zulässig. Es gibt ein Wrapperelement für die gesamte Sammlung und ein separates Wrapperelement (ähnlich wie <myDataMember> im vorherigen Beispiel) für jedes XmlNode-Array im äußeren Array oder in der äußeren Sammlung.

Das Auffüllen eines Datenmembers vom Typ Array von Object oder Array von IEnumerable mit XmlNode-Instanzen führt nicht dazu, dass der Datenmember als Array mit XmlNode-Instanzen behandelt wird. Jedes Arrayelement wird separat serialisiert.

Bei Verwendung mit dem DataContractSerializer können Arrays von XmlNode polymorph zugewiesen werden, jedoch nur einem Datenelement vom Typ Object. Auch wenn es IEnumerable implementiert, kann ein XmlNode-Array nicht als Auflistungstyp verwendet und keinem IEnumerable-Datenmember zugeordnet werden. Wie bei allen polymorphen Zuweisungen wird im resultierenden XML-Code der Datenvertragsname vom DataContractSerializer ausgegeben – in diesem Fall ist es "ArrayOfXmlNode" im http://schemas.datacontract.org/2004/07/System.Xml Namespace. Bei Verwendung mit dem NetDataContractSerializer wird jede gültige Zuweisung eines XmlNode Arrays unterstützt.

Schemaüberlegungen

Ausführliche Informationen zur Schemazuordnung von XML-Typen finden Sie unter Data Contract Schema Reference. Dieser Abschnitt enthält eine Zusammenfassung der wichtigen Punkte.

Ein Datenmitglied des Typs XmlElement ist auf ein Element abgebildet, das mithilfe des folgenden anonymen Typs definiert ist.

<xsd:complexType>  
   <xsd:sequence>  
      <xsd:any minOccurs="0" processContents="lax" />  
   </xsd:sequence>  
</xsd:complexType>  

Ein Datenelement vom Typ Array of XmlNode wird einem Element zugeordnet, das mithilfe des folgenden anonymen Typs definiert ist.

<xsd:complexType mixed="true">  
   <xsd:sequence>  
      <xsd:any minOccurs="0" maxOccurs="unbounded" processContents="lax" />  
   </xsd:sequence>  
   <xsd:anyAttribute/>  
</xsd:complexType>  

Typen, die die IXmlSerializable-Schnittstelle implementieren

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

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

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

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

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

IXmlSerialisierbare Inhaltstypen

Beim Serialisieren eines Datenmitglieds eines Typs, der IXmlSerializable implementiert und ein zuvor definierter Inhaltstyp ist, schreibt der Serialisierer das Wrapperelement für das Datenmitglied und übergibt die Kontrolle an die WriteXml Methode. Die WriteXml Implementierung kann einen beliebigen XML-Code schreiben, einschließlich des Hinzufügens von Attributen zum Wrapperelement. Nachdem WriteXml abgeschlossen ist, schließt das Serialisierungsprogramm das Element.

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

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

Attribute, die ignoriert werden, wenn ReadXml implementiert wird

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

Schemaüberlegungen für IXmlSerializable-Inhaltstypen

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

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

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

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

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

IXmlSerializable-Elementtypen

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

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

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

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

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

  • Beim Serialisieren eines Elementtyps auf oberster Ebene ohne Angabe des Stammnamens und des Namespaces zur Erstellungszeit tun WriteStartObject und WriteEndObject nichts, und WriteObjectContent ruft WriteXml auf. In diesem Modus kann das serialisierte Objekt nicht null sein und kann nicht polymorph zugewiesen werden. Außerdem kann die Objektdiagramm-Erhaltung nicht aktiviert werden, und das NetDataContractSerializer kann nicht verwendet werden.

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

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

Unterschiede zum XmlSerializer

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

  • Die Schemaanbietermethode muss öffentlich sein, damit sie im XmlSerializerDatenvertragsmodell verwendet werden kann, aber nicht öffentlich sein muss.

  • Die Schemaanbietermethode wird aufgerufen, wenn IsAny im Datenvertragsmodell wahr ist, jedoch nicht mit XmlSerializer zutrifft.

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

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

Importieren eines IXmlSerializable-Schemas

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

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

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

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

Darstellen beliebiger XML-Daten in Datenverträgen

Mithilfe der Typen XmlElement, XmlNode-Array und IXmlSerializable können Sie beliebige XML-Daten in das Datenvertragsmodell einfügen. Der DataContractSerializer und der NetDataContractSerializer geben diesen XML-Inhalt an den verwendeten XML-Writer weiter, ohne den Prozess zu beeinträchtigen. Die XML-Autoren erzwingen jedoch möglicherweise bestimmte Einschränkungen für den xml-Code, den sie schreiben. Hier sind einige wichtige Beispiele:

  • Die XML-Schreiber erlauben typischerweise keine XML-Dokumentdeklaration (z. B. <?xml version='1.0' ?>) während des Schreibens eines anderen Dokuments. Sie können kein vollständiges XML-Dokument als Array-XmlNode für einen Datenmember serialisieren. Dazu müssen Sie entweder die Dokumentdeklaration entfernen oder ihr eigenes Codierungsschema verwenden, um es darzustellen.

  • Alle MIT WCF bereitgestellten XML-Autoren weisen XML-Verarbeitungsanweisungen (<? ... ?>) und Dokumenttypdefinitionen (<! ... >) zurück, da sie in SOAP-Nachrichten nicht zulässig sind. Auch hier können Sie ihren eigenen Codierungsmechanismus verwenden, um diese Einschränkung zu umgehen. Wenn Sie diese in Ihr resultierendes XML einschließen müssen, können Sie einen benutzerdefinierten Encoder schreiben, der XML-Autoren verwendet, die sie unterstützen.

  • Vermeiden Sie bei der Implementierung von WriteXml, die WriteRaw-Methode für den XML-Writer aufzurufen. WCF verwendet eine Vielzahl von XML-Codierungen (einschließlich binär), es ist sehr schwierig oder unmöglich, so zu verwenden WriteRaw , dass das Ergebnis in jeder Codierung verwendet werden kann.

  • Vermeiden Sie bei der Implementierung WriteXml die Verwendung der WriteEntityRef- und WriteNmToken-Methoden, die von den mit WCF bereitgestellten XML-Schreibern nicht unterstützt werden.

Verwenden von DataSet, typisiertem DataSet und DataTable

Die Verwendung dieser Typen wird im Datenvertragsmodell vollständig unterstützt. Berücksichtigen Sie bei der Verwendung dieser Typen die folgenden Punkte:

  • Das Schema für diese Typen (insbesondere DataSet und seine typierten abgeleiteten Klassen) ist möglicherweise nicht mit einigen Nicht-WCF-Plattformen interoperabel oder kann zu einer schlechten Nutzbarkeit führen, wenn sie mit diesen Plattformen verwendet wird. Darüber hinaus kann die Verwendung des DataSet Typs Auswirkungen auf die Leistung haben. Schließlich kann es für Sie schwieriger sein, Ihre Anwendung in Zukunft zu versionieren. Erwägen Sie, explizit definierte Datentypen anstelle von DataSet Typen in Ihren Verträgen zu verwenden.

  • Beim Importieren DataSet oder DataTable Schema ist es wichtig, auf diese Typen zu verweisen. Mit dem Svcutil.exe Befehlszeilentool kann dies erreicht werden, indem der System.Data.dll Assemblyname an den /reference Switch übergeben wird. Beim Importieren des typisierten Datasetschemas müssen Sie auf den Typ des typisierten Datasets verweisen. Übergeben Sie bei Verwendung von „Svcutil.exe“ den Speicherort der Assembly des typisierten Datasets an die Option /reference. Weitere Informationen zum Verweisen auf Typen finden Sie im Importschema zum Generieren von Klassen.

Die Unterstützung für typierte DataSets im Datenvertragsmodell ist eingeschränkt. Typisierte DataSets können serialisiert und deserialisiert werden und ihr Schema exportieren. Der Datenvertragsschemaimport kann jedoch keine neuen typierten DataSet-Typen aus dem Schema generieren, da vorhandene nur wiederverwendet werden können. Sie können mithilfe des /r-Schalters von Svcutil.exe auf ein vorhandenes typisiertes DataSet verweisen. Wenn Sie versuchen, eine Svcutil.exe ohne den Schalter /r bei einem Dienst zu verwenden, der ein typisiertes Dataset verwendet, wird automatisch ein alternativer Serializer (XmlSerializer) ausgewählt. Wenn Sie den DataContractSerializer verwenden und DataSets aus dem Schema generieren müssen, können Sie das folgende Verfahren anwenden: Generieren Sie die typisierten DataSet-Typen (mithilfe des Tools Xsd.exe mit dem /d Schalter auf dem Dienst), kompilieren Sie die Typen und verweisen Sie dann mithilfe des /r Schalters auf Svcutil.exe.

Siehe auch