数据协定是服务与客户端之间的正式协议,用于抽象描述要交换的数据。 也就是说,为了通信,客户端和服务不必共享相同的类型,只有相同的数据协定。 数据协定为每个参数或返回类型精确定义为进行交换而序列化哪些数据(将哪些数据转换为 XML)。
数据协定基础知识
Windows Communication Foundation (WCF) 默认使用称为数据协定序列化程序的序列化引擎来序列化和反序列化数据(将其转换为 XML)。 所有 .NET Framework 基元类型(如整数和字符串),以及被视为基元的某些类型(例如 DateTime ,和 XmlElement)都可以进行序列化,而无需进行其他准备,并被视为具有默认数据协定。 许多 .NET Framework 类型也具有现有的数据协定。 有关可序列化类型的完整列表,请参阅 数据协定序列化程序支持的类型。
你创建的新复杂类型必须定义一个数据协定,以便其可序列化。 默认情况下,DataContractSerializer 推理数据协定并序列化所有公开可见的类型。 类型的所有公共读/写属性和字段均被序列化。 可以使用 IgnoreDataMemberAttribute从序列化中剔除某些成员。 还可以使用 DataContractAttribute 和 DataMemberAttribute 属性显式创建数据协定。 这通常是通过将属性应用于 DataContractAttribute 类型来完成的。 此属性可以应用于类、结构和枚举。 然后,必须将该 DataMemberAttribute 属性应用于数据协定类型的每个成员,以指示它是 一个数据成员,即应对其进行序列化。 有关详细信息,请参阅 可序列化类型。
示例:
下面的示例演示已经显式应用了 ServiceContractAttribute 和 OperationContractAttribute 属性的服务协定(接口)。 该示例显示基元类型不需要数据协定,而复杂类型则不需要数据协定。
[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
以下示例演示了如何通过将MyTypes.PurchaseOrder
和DataContractAttribute属性应用于类及其成员来创建DataMemberAttribute类型的数据契约。
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
注释
以下说明提供了创建数据协定时要考虑的项目:
仅当与未标记类型一起使用时,该IgnoreDataMemberAttribute 属性才起作用。 这包括未用DataContractAttribute、SerializableAttribute、CollectionDataContractAttribute或EnumMemberAttribute等属性标记,或者未通过任何其他方式(例如IXmlSerializable)标记为可序列化的类型。
可以将 DataMemberAttribute 属性应用于字段和特性。
成员访问级别(内部、私有、受保护或公共)不会以任何方式影响数据契约。
DataMemberAttribute如果属性应用于静态成员,则忽略该属性。
在序列化过程中,调用属性访问代码来获取要序列化的属性数据成员的值。
在反序列化期间,会首先创建未初始化的对象,而不调用类型上的任何构造函数。 然后,将反序列化所有数据成员。
在反序列化期间,为属性数据成员调用属性集代码,以将属性设置为要反序列化的值。
若要使数据协定有效,必须能够序列化其所有数据成员。 有关可序列化类型的完整列表,请参阅 数据协定序列化程序支持的类型。
泛型类型处理方式与非泛型类型完全相同。 泛型参数没有特殊要求。 例如,请考虑以下类型。
[DataContract]
public class MyGenericType1<T>
{
// Code not shown.
}
<DataContract()> _
Public Class MyGenericType1(Of T)
' Code not shown.
End Class
无论用于泛型类型参数 (T
) 的类型是否可序列化,此类型都是可序列化的。 由于必须能够序列化所有数据成员,因此只有在泛型类型参数也可序列化时,该类型才是可序列化的,如以下代码所示。
[DataContract]
public class MyGenericType2<T>
{
[DataMember]
T theData;
}
<DataContract()> _
Public Class MyGenericType2(Of T)
<DataMember()> _
Dim theData As T
End Class
有关定义数据协定的 WCF 服务的完整代码示例,请参阅 基本数据协定 示例。