Verwenden von Datenverträgen

Ein neuer Datenvertrag ist eine formale Vereinbarung zwischen einem Dienst und einem Client, in dem die auszutauschenden Daten abstrakt beschrieben werden. Das heißt, der Client und der Dienst müssen, um kommunizieren zu können, nicht denselben Typ verwenden, sondern nur dieselben Datenverträge. Ein Datenvertrag definiert für jeden Parameter oder Rückgabetyp genau, welche Daten für einen Austausch serialisiert (in XML umgewandelt) werden.

Grundlagen des Datenvertrags

Windows Communication Foundation (WCF) verwendet zum Serialisieren und Deserialisieren von Daten (Umwandeln in und aus XML) standardmäßig eine Serialisierungs-Engine für Datenverträge (Data Contract Serializer). Alle primitiven Typen von .NET Framework, wie Ganzzahlen und Zeichenfolgen, sowie bestimmte als Primitive behandelte Typen, wie DateTime und XmlElement, können ohne weitere Vorbereitung serialisiert werden und sind gewissermaßen mit Standarddatenverträgen ausgestattet. Viele .NET Framework-Typen verfügen auch über vorhandene Datenverträge. Eine vollständige Liste der serialisierbaren Typen finden Sie unter Types Supported by the Data Contract Serializer.

Für neue komplexe Typen, die Sie erstellen, muss ein Datenvertrag definiert sein, damit sie serialisierbar sind. Standardmäßig leitet der DataContractSerializer den Datenvertrag ab und serialisiert alle öffentlich sichtbaren Typen. Alle öffentlichen Lese-/Schreibeigenschaften und Felder des Typs werden serialisiert. Mithilfe des IgnoreDataMemberAttributekönnen Member von der Serialisierung ausgeschlossen werden. Mit dem DataContractAttribute -Attribut und dem DataMemberAttribute -Attribut können Sie auch explizit einen Datenvertrag erstellen. Wenden Sie dazu das DataContractAttribute -Attribut auf den Typ an. Dieses Attribut kann auf Klassen, Strukturen und Enumerationen angewendet werden. Das DataMemberAttribute -Attribut muss dann auf jeden Member des Datenvertragstyps angewendet werden, um anzugeben, dass es sich um einen Datenmemberhandelt, d. h., dass er serialisiert werden soll. Weitere Informationen finden Sie unter Serialisierbare Typen.

Beispiel

Im folgenden Beispiel wird ein Dienstvertrag (eine Schnittstelle) dargestellt, auf die die Attribute ServiceContractAttribute und OperationContractAttribute explizit angewendet wurden. Das Beispiel zeigt, dass primitive Typen keinen Datenvertrag erfordern, ein komplexer Typ jedoch schon.

[ServiceContract]
public interface ISampleInterface
{
    // No data contract is required since both the parameter
    // and return types are primitive types.
    [OperationContract]
    double SquareRoot(int root);

    // No Data Contract required because both parameter and return
    // types are marked with the SerializableAttribute attribute.
    [OperationContract]
    System.Drawing.Bitmap GetPicture(System.Uri pictureUri);

    // The MyTypes.PurchaseOrder is a complex type, and thus
    // requires a data contract.
    [OperationContract]
    bool ApprovePurchaseOrder(MyTypes.PurchaseOrder po);
}
<ServiceContract()> _
Public Interface ISampleInterface
    ' No data contract is required since both the parameter and return 
    ' types are both primitive types.
    <OperationContract()> _
    Function SquareRoot(ByVal root As Integer) As Double

    ' No Data Contract required because both parameter and return 
    ' types are marked with the SerializableAttribute attribute.
    <OperationContract()> _
    Function GetPicture(ByVal pictureUri As System.Uri) As System.Drawing.Bitmap

    ' The MyTypes.PurchaseOrder is a complex type, and thus 
    ' requires a data contract.
    <OperationContract()> _
    Function ApprovePurchaseOrder(ByVal po As MyTypes.PurchaseOrder) As Boolean
End Interface

Das folgende Beispiel veranschaulicht, wie Sie einen Datenvertrag für den MyTypes.PurchaseOrder -Typ erstellen, indem Sie die Attribute DataContractAttribute und DataMemberAttribute auf die Klassen und ihre Member anwenden.

namespace MyTypes
{
    [DataContract]
    public class PurchaseOrder
    {
        private int poId_value;

        // Apply the DataMemberAttribute to the property.
        [DataMember]
        public int PurchaseOrderId
        {

            get { return poId_value; }
            set { poId_value = value; }
        }
    }
}
Namespace MyTypes
    <System.Runtime.Serialization.DataContractAttribute()> _
    Public Class PurchaseOrder
        Private poId_value As Integer

        ' Apply the DataMemberAttribute to the property.

        <DataMember()> _
        Public Property PurchaseOrderId() As Integer

            Get
                Return poId_value
            End Get
            Set
                poId_value = value
            End Set
        End Property
    End Class
End Namespace

Hinweise

Berücksichtigen Sie beim Erstellen von Datenverträgen die folgenden Hinweise:

  • Das IgnoreDataMemberAttribute -Attribut wird nur berücksichtigt, wenn es zusammen mit nicht markierten Typen verwendet wird. Dazu zählen Typen, die weder mit einem DataContractAttribute-, SerializableAttribute-, CollectionDataContractAttribute- oder EnumMemberAttribute -Attribut noch auf andere Weise als serialisierbar markiert sind (beispielsweise mithilfe von IXmlSerializable).

  • Sie können das DataMemberAttribute -Attribut auf Felder und Eigenschaften anwenden.

  • Memberzugriffsebenen (internal, private, protected oder public) haben keinerlei Einfluss auf den Datenvertrag.

  • Das DataMemberAttribute -Attribut wird ignoriert, wenn es auf statische Member angewendet wird.

  • Bei der Serialisierung werden mit einem Aufruf von property-get-Code für Eigenschaftsdatenmember die Werte der zu serialisierenden Eigenschaften abgerufen.

  • Bei der Deserialisierung wird zuerst ein nicht initialisiertes Objekt erstellt, ohne dass Konstruktoren für den Typ aufgerufen werden. Dann werden alle Datenmember deserialisiert.

  • Mit einem Aufruf von property-set-Code für Eigenschaftsdatenmember werden bei der Deserialisierung die Werte der zu deserialisierenden Eigenschaften festgelegt.

  • Damit ein Datenvertrag gültig ist, müssen alle seine Datenmember serialisiert werden können. Eine vollständige Liste der serialisierbaren Typen finden Sie unter Types Supported by the Data Contract Serializer.

    Generische Typen werden auf genau die gleiche Weise behandelt wie nicht generische Typen. Es gibt keine besonderen Anforderungen für generische Parameter. Betrachten Sie z. B. den folgenden Typ:

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

Dieser Typ ist serialisierbar, unabhängig davon, ob der für den generischen Typparameter (T) verwendete Typ serialisierbar ist. Da das Serialisieren aller Datenmember möglich sein muss, ist der folgende Typ nur dann serialisierbar, wenn der generische Typparameter ebenfalls serialisierbar ist (wie im folgenden Code dargestellt):

[DataContract]
public class MyGenericType2<T>
{
    [DataMember]
    T theData;
}
<DataContract()> _
Public Class MyGenericType2(Of T)
    <DataMember()> _
    Dim theData As T
End Class

Ein vollständiges Codebeispiel eines WCF-Diensts, der einen Datenvertrag definiert, finden Sie unter Basic Data Contract .

Weitere Informationen