Dela via


Använda datakontrakt

Ett datakontrakt är ett formellt avtal mellan en tjänst och en klient som abstrakt beskriver de data som ska utbytas. För att kommunicera behöver klienten och tjänsten inte dela samma typer, bara samma datakontrakt. Ett datakontrakt definierar exakt för varje parameter eller returtyp vilka data som ska serialiseras (omvandlas till XML).

Grunderna i datakontrakt

Windows Communication Foundation (WCF) använder en serialiseringsmotor som kallas Data Contract Serializer som standard för att serialisera och deserialisera data (konvertera dem till och från XML). Alla primitiva .NET Framework-typer, till exempel heltal och strängar, samt vissa typer som behandlas som primitiver, till DateTime exempel och XmlElement, kan serialiseras utan någon annan förberedelse och anses ha standarddatakontrakt. Många .NET Framework-typer har också befintliga datakontrakt. En fullständig lista över serialiserbara typer finns i Typer som stöds av Data Contract Serializer.

Nya komplexa typer som du skapar måste ha ett datakontrakt definierat för att de ska kunna serialiseras. Som standard DataContractSerializer härleder slutsatsdragningen datakontraktet och serialiserar alla offentligt synliga typer. Alla offentliga läs-/skrivegenskaper och fält av typen serialiseras. Du kan välja bort medlemmar från serialisering med hjälp IgnoreDataMemberAttributeav . Du kan också uttryckligen skapa ett datakontrakt med hjälp DataContractAttribute av och DataMemberAttribute attribut. Detta görs normalt genom att attributet tillämpas DataContractAttribute på typen. Det här attributet kan tillämpas på klasser, strukturer och uppräkningar. Attributet DataMemberAttribute måste sedan tillämpas på varje medlem i datakontraktstypen för att indikera att det är en datamedlem, det vill sa att det ska serialiseras. Mer information finns i Serializable Types (Serializable Types).

Exempel

I följande exempel visas ett tjänstkontrakt (ett gränssnitt) som attributen och OperationContractAttribute uttryckligen ServiceContractAttribute har tillämpats på. Exemplet visar att primitiva typer inte kräver ett datakontrakt, medan en komplex typ gör det.

[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

I följande exempel visas hur ett datakontrakt för MyTypes.PurchaseOrder typen skapas genom att attributen DataContractAttribute och DataMemberAttribute tillämpas på klassen och dess medlemmar.

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

Kommentar

Följande anteckningar innehåller saker att tänka på när du skapar datakontrakt:

  • Attributet IgnoreDataMemberAttribute respekteras endast när det används med omärkta typer. Detta inkluderar typer som inte har markerats med något av attributen DataContractAttribute, SerializableAttribute, CollectionDataContractAttributeeller eller EnumMemberAttribute som markerats som serialiserbara på något annat sätt (till exempel IXmlSerializable).

  • Du kan använda attributet DataMemberAttribute för fält och egenskaper.

  • Tillgänglighetsnivåer för medlemmar (interna, privata, skyddade eller offentliga) påverkar inte datakontraktet på något sätt.

  • Attributet DataMemberAttribute ignoreras om det tillämpas på statiska medlemmar.

  • Under serialiseringen anropas egenskaps-get-kod för egenskapsdatamedlemmar för att hämta värdet för de egenskaper som ska serialiseras.

  • Under deserialiseringen skapas först ett onitialiserat objekt, utan att anropa några konstruktorer för typen. Sedan deserialiseras alla datamedlemmar.

  • Under deserialiseringen anropas egenskapsuppsättningskod för egenskapsdatamedlemmar för att ange egenskaperna till det värde som deserialiseras.

  • För att ett datakontrakt ska vara giltigt måste det vara möjligt att serialisera alla dess datamedlemmar. En fullständig lista över serialiserbara typer finns i Typer som stöds av Data Contract Serializer.

    Generiska typer hanteras på exakt samma sätt som icke-generiska typer. Det finns inga särskilda krav för generiska parametrar. Tänk till exempel på följande typ.

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

Den här typen kan serialiseras oavsett om den typ som används för den generiska typparametern (T) är serialiserbar eller inte. Eftersom det måste vara möjligt att serialisera alla datamedlemmar är följande typ serialiserbar endast om parametern för den generiska typen också är serialiserbar, enligt följande kod.

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

Ett fullständigt kodexempel för en WCF-tjänst som definierar ett datakontrakt finns i exemplet grundläggande datakontrakt .

Se även