데이터 계약은 교환할 데이터를 추상적으로 설명하는 서비스와 클라이언트 간의 공식 계약입니다. 즉, 통신하기 위해 클라이언트와 서비스는 동일한 형식을 공유할 필요가 없으며 동일한 데이터 계약만 공유하면 됩니다. 데이터 계약은 각 매개 변수 또는 반환 형식에 대해 교환할 데이터를 직렬화(XML로 변환)하는 데이터를 정확하게 정의합니다.
데이터 계약 기본 사항
WCF(Windows Communication Foundation)는 기본적으로 데이터 계약 직렬 변환기라는 직렬화 엔진을 사용하여 데이터를 직렬화 및 역직렬화합니다(XML로 변환). 정수 및 문자열과 같은 모든 .NET Framework 기본 형식과 같은 기본 형식으로 처리되는 특정 형식(예: DateTime 및 XmlElement)은 다른 준비 없이 직렬화할 수 있으며 기본 데이터 계약이 있는 것으로 간주됩니다. 많은 .NET Framework 형식에도 기존 데이터 계약이 있습니다. 직렬화 가능한 형식의 전체 목록은 데이터 계약 직렬 변환기에서 지원하는 형식을 참조하세요.
새로 만드는 복합 형식에는 직렬화할 수 있도록 정의된 데이터 계약이 있어야 합니다. 기본적으로 DataContractSerializer 데이터 계약을 유추하고 공개적으로 표시되는 모든 형식을 직렬화합니다. 형식의 모든 공용 읽기/쓰기 속성 및 필드가 직렬화됩니다. IgnoreDataMemberAttribute를 사용하여 serialization에서 멤버를 제외할 수 있습니다. 또한 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
)에 사용되는 형식을 직렬화할 수 있는지 여부를 직렬화할 수 있습니다. 모든 데이터 멤버를 직렬화할 수 있어야 하므로 다음 코드와 같이 제네릭 형식 매개 변수도 serialize할 수 있는 경우에만 다음 형식을 serialize할 수 있습니다.
[DataContract]
public class MyGenericType2<T>
{
[DataMember]
T theData;
}
<DataContract()> _
Public Class MyGenericType2(Of T)
<DataMember()> _
Dim theData As T
End Class
데이터 계약을 정의하는 WCF 서비스의 전체 코드 샘플은 기본 데이터 계약 샘플을 참조하세요.