Condividi tramite


Uso dei contratti dati

Un contratto dati è un contratto formale tra un servizio e un cliente che descrive in modo astratto i dati da scambiare. Ovvero, per comunicare, il client e il servizio non devono condividere gli stessi tipi, solo gli stessi contratti dati. Un contratto dati definisce con precisione, per ogni parametro o tipo restituito, quali dati vengono serializzati (trasformati in XML) da scambiare.

Nozioni di base sul contratto dati

Windows Communication Foundation (WCF) usa di default un motore di serializzazione denominato Serializzatore del contratto dati per serializzare e deserializzare i dati (convertendoli da e in XML). Tutti i tipi primitivi di .NET Framework, ad esempio numeri interi e stringhe, nonché determinati tipi trattati come primitive, ad esempio DateTime e XmlElement, possono essere serializzati senza altre operazioni di preparazione e vengono considerati come contratti dati predefiniti. Molti tipi .NET Framework hanno anche contratti dati esistenti. Per un elenco completo dei tipi serializzabili, vedere Tipi supportati dal serializzatore di contratti dati.

I nuovi tipi complessi creati devono avere un contratto dati definito affinché siano serializzabili. Per impostazione predefinita, DataContractSerializer deduce il contratto di dati e serializza tutti i tipi visibili pubblicamente. Tutte le proprietà e i campi pubblici di lettura/scrittura del tipo vengono serializzati. È possibile escludere i membri dalla serializzazione usando IgnoreDataMemberAttribute. È anche possibile creare in modo esplicito un contratto dati usando DataContractAttribute gli attributi e DataMemberAttribute . Questa operazione viene in genere eseguita applicando l'attributo DataContractAttribute al tipo . Questo attributo può essere applicato a classi, strutture ed enumerazioni. L'attributo DataMemberAttribute deve quindi essere applicato a ogni membro del tipo di contratto dati per indicare che è un membro dati, ovvero deve essere serializzato. Per altre informazioni, vedere Tipi serializzabili.

Esempio

Nell'esempio seguente viene illustrato un contratto di servizio (un'interfaccia) a cui sono stati applicati in modo esplicito gli ServiceContractAttribute attributi e OperationContractAttribute . L'esempio mostra che i tipi primitivi non richiedono un contratto dati, mentre un tipo complesso lo fa.

[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

Nell'esempio seguente viene illustrato come viene creato un contratto dati per il MyTypes.PurchaseOrder tipo applicando gli DataContractAttribute attributi e DataMemberAttribute alla classe e ai relativi membri.

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

Note

Le note seguenti forniscono elementi da considerare durante la creazione di contratti dati:

  • L'attributo IgnoreDataMemberAttribute viene rispettato solo se usato con tipi non contrassegnati. Sono inclusi i tipi che non sono contrassegnati con uno degli attributi DataContractAttribute, SerializableAttribute, CollectionDataContractAttribute, o EnumMemberAttribute, né contrassegnati come serializzabili in qualsiasi altro modo, ad esempio con IXmlSerializable.

  • È possibile applicare l'attributo DataMemberAttribute ai campi e alle proprietà.

  • I livelli di accessibilità dei membri (interni, privati, protetti o pubblici) non influiscono sul contratto dati in alcun modo.

  • L'attributo DataMemberAttribute viene ignorato se viene applicato ai membri statici.

  • Durante la serializzazione, il codice property-get viene chiamato per i membri dei dati delle proprietà per ottenere il valore delle proprietà da serializzare.

  • Durante la deserializzazione, viene creato un oggetto non inizializzato, senza invocare alcun costruttore della classe. Tutti i membri dati vengono quindi deserializzati.

  • Durante la deserializzazione, viene chiamato il codice di impostazione delle proprietà per impostare le proprietà al valore in fase di deserializzazione.

  • Affinché un contratto dati sia valido, è necessario serializzare tutti i relativi membri dati. Per un elenco completo dei tipi serializzabili, vedere Tipi supportati dal serializzatore di contratti dati.

    I tipi generici vengono gestiti esattamente come i tipi non generici. Non esistono requisiti speciali per i parametri generici. Si consideri ad esempio il tipo seguente.

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

Questo tipo è serializzabile se il tipo usato per il parametro di tipo generico (T) è serializzabile o meno. Poiché deve essere possibile serializzare tutti i membri dati, il tipo seguente è serializzabile solo se il parametro di tipo generico è serializzabile, come illustrato nel codice seguente.

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

Per un esempio di codice completo di un servizio WCF che definisce un contratto dati, vedere l'esempio di Contratto dati di base .

Vedere anche