Utilizzo di contratti dati
Un contratto dati è un accordo formale tra un servizio e un client che descrive astrattamente i dati da scambiare. Per comunicare, non è necessario che il client e il servizio condividano gli stessi tipi, ma solo gli stessi contratti dati. Un contratto dati definisce con precisione, per ogni parametro o tipo restituito, i dati serializzati (trasformati in XML) che verranno scambiati.
Nozioni fondamentali dei contratti dati
Per impostazione predefinita in Windows Communication Foundation (WCF) viene utilizzato un motore di serializzazione denominato serializzatore dei contratti dati per serializzare e deserializzare i dati (convertendoli in/da XML). Ogni tipo primitivo .NET Framework, ad esempio numeri interi e stringhe, nonché alcuni tipi trattati come primitivi, ad esempio DateTime e XmlElement, può essere serializzato senza ulteriore preparazione ed è considerato in possesso di contratti dati predefiniti. I tipi .NET Framework, inoltre, dispongono di contratti dati esistenti. Per un elenco completo di tipi serializzabili, vedere Tipi supportati dal serializzatore dei contratti dati.
Per poter essere serializzabili, è necessario che i nuovi tipi complessi creati dispongano di un contratto dati appositamente definito. Per impostazione predefinita, tramite DataContractSerializer viene dedotto il contratto dati e vengono serializzati tutti i tipi visibili pubblicamente. Vengono serializzati tutti i campi e le proprietà di lettura/scrittura pubblici del tipo. È possibile rifiutare esplicitamente i membri per la serializzazione tramite IgnoreDataMemberAttribute. È inoltre possibile creare in modo esplicito un contratto dati utilizzando gli attributi DataContractAttribute e DataMemberAttribute. Ciò viene di norma realizzato 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 si tratta di un membro dati, ovvero che deve essere serializzato. Per ulteriori 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 attributi ServiceContractAttribute e OperationContractAttribute. Nell'esempio viene mostrato che i tipi primitivi non richiedono un contratto dati, diversamente da un tipo complesso.
<ServiceContract()> _
Public Interface ISampleInterface
' No data contract is requred 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
[ServiceContract]
public interface ISampleInterface
{
// No data contract is requred 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);
}
Nell'esempio seguente viene illustrato come creare un contratto dati per il tipo MyTypes.PurchaseOrder
creato applicando gli attributi DataContractAttribute e DataMemberAttribute alla classe e ai relativi membri.
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
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; }
}
}
}
Note
Nelle note seguenti sono contenuti gli elementi da tenere presenti durante la creazione di contratti dati:
L'attributo IgnoreDataMemberAttribute viene accettato solo se utilizzato con tipi non contrassegnati. Sono inclusi i tipi non contrassegnati con uno degli attributi DataContractAttribute, SerializableAttribute, CollectionDataContractAttribute o EnumMemberAttribute oppure contrassegnati come serializzabili in qualsiasi altro modo (ad esempio IXmlSerializable).
È possibile applicare l'attributo DataMemberAttribute a campi e proprietà.
I livelli di accessibilità ai membri (interno, privato, protetto o pubblico) non influiscono in alcun modo sul contratto dati.
L'attributo DataMemberAttribute viene ignorato se applicato a membri statici.
Durante la serializzazione il codice della proprietà get viene chiamato per i membri dati della proprietà per ottenere il valore delle proprietà da serializzare.
Durante la deserializzazione viene prima creato un oggetto non inizializzato, senza chiamare alcun costruttore per il tipo, quindi vengono deserializzati tutti i membri dati.
Durante la deserializzazione il codice della proprietà set viene chiamato per i membri dati della proprietà per impostare le proprietà sul valore in fase di deserializzazione.
Perché un contratto dati sia valido, deve essere possibile serializzare tutti i relativi membri dati. Per un elenco completo di tipi serializzabili, vedere Tipi supportati dal serializzatore dei contratti dati.
I tipi generici sono gestiti esattamente nello stesso modo dei tipi non generici. Non vi sono requisiti speciali per i parametri generici. Si consideri ad esempio il tipo seguente:
<DataContract()> _
Public Class MyGenericType1 (Of T)
' Code not shown.
End Class
[DataContract]
public class MyGenericType1<T>
{
// Code not shown.
}
Il tipo è serializzabile indipendentemente dal fatto che il tipo utilizzato per il parametro di tipo generico (T) sia serializzabile o meno. Poiché deve essere possibile serializzare tutti i membri dati, il tipo seguente è serializzabile solo se il parametro di tipo generico è anch'esso serializzabile, come indicato nel codice seguente.
<DataContract()> Public Class MyGenericType2(Of T)
<DataMember()> Dim theData As T
End Class
[DataContract]
public class MyGenericType2<T>
{
[DataMember]
T theData;
}
Vedere anche
Attività
Procedura: creare un contratto dati di base per una classe o una struttura
Riferimento
DataMemberAttribute
DataContractAttribute
Concetti
Tipi serializzabili
Nomi di contratto dati
Equivalenza dei contratti dati
Ordine dei membri dati
Tipi conosciuti di contratto dati
Contratti dati compatibili con versioni successive
Controllo delle versioni dei contratti dati
Callback di serializzazione a tolleranza di versione
Valori predefiniti dei membri dati
Tipi supportati dal serializzatore dei contratti dati