서비스 계약에서 데이터 전송 지정

WCF(Windows Communication Foundation)는 메시징 인프라로 간주할 수 있습니다. 서비스 작업에서는 메시지를 받고 처리한 다음 보낼 수 있습니다. 메시지는 작업 계약을 사용하여 설명됩니다. 다음 계약을 예로 들 수 있습니다.

[ServiceContract]  
public interface IAirfareQuoteService  
{  
    [OperationContract]  
    float GetAirfare(string fromCity, string toCity);  
}  
<ServiceContract()>  
Public Interface IAirfareQuoteService  
  
    <OperationContract()>  
    Function GetAirfare(fromCity As String, toCity As String) As Double  
End Interface  

여기서 GetAirfare 작업은 fromCitytoCity에 대한 정보가 있는 메시지를 수락한 다음 숫자가 포함된 메시지를 반환합니다.

이 항목에서는 작업 계약에서 메시지를 설명할 수 있는 여러 가지 방법에 대해 설명합니다.

매개 변수를 사용하여 메시지 설명

메시지를 설명하는 가장 간단한 방법은 매개 변수 목록과 반환 값을 사용하는 것입니다. 앞의 예제에서 fromCitytoCity 문자열 매개 변수는 요청 메시지를 설명하는 데 사용되었고 float 반환 값은 회신 메시지를 설명하는 데 사용되었습니다. 반환 값으로만 회신 메시지를 설명할 수 없는 경우에는 out 매개 변수를 사용할 수도 있습니다. 예를 들어, 다음 연산의 경우 요청 메시지에는 fromCitytoCity가 있으며 회신 메시지에는 통화와 숫자가 함께 있습니다.

[OperationContract]  
float GetAirfare(string fromCity, string toCity, out string currency);  
<OperationContract()>  
    Function GetAirfare(fromCity As String, toCity As String) As Double  

또한 참조 매개 변수를 사용하여 요청 및 회신 메시지의 매개 변수 부분을 만들 수 있습니다. 매개 변수는 serialize할 수 있는, 즉 XML로 변환할 수 있는 형식이어야 합니다. 기본적으로 WCF에서는 DataContractSerializer 클래스라고 하는 구성 요소를 사용하여 이 변환을 수행합니다. int, string, floatDateTime과 같은 가장 기본적인 형식이 지원됩니다. 사용자 정의 형식에는 일반적으로 데이터 계약이 있어야 합니다. 자세한 내용은 데이터 계약 사용을 참조하세요.

public interface IAirfareQuoteService  
{  
    [OperationContract]  
    float GetAirfare(Itinerary itinerary, DateTime date);  
  
    [DataContract]  
    public class Itinerary  
    {  
        [DataMember]  
        public string fromCity;  
        [DataMember]  
        public string toCity;  
   }  
}  
Public Interface IAirfareQuoteService  
    <OperationContract()>  
    GetAirfare(itinerary as Itinerary, date as DateTime) as Double  
  
    <DataContract()>  
    Class Itinerary  
  
        <DataMember()>  
        Public fromCity As String  
        <DataMember()>  
        Public toCity As String  
    End Class  
End Interface  

DataContractSerializer는 사용자의 형식을 serialize하기에 적합하지 않은 경우도 있습니다. WCF에서는 대체 serialization 엔진인 XmlSerializer를 지원하므로, 이 엔진을 사용하여 매개 변수를 serialize할 수도 있습니다. XmlSerializer를 통해 XmlAttributeAttribute와 같은 특성을 사용하여 결과 XML을 보다 효과적으로 제어할 수 있습니다. 특정 연산이나 전체 서비스에 XmlSerializer를 사용하려면 XmlSerializerFormatAttribute 특성을 연산이나 서비스에 적용합니다. 예시:

[ServiceContract]  
public interface IAirfareQuoteService  
{  
    [OperationContract]  
    [XmlSerializerFormat]  
    float GetAirfare(Itinerary itinerary, DateTime date);  
}  
public class Itinerary  
{  
    public string fromCity;  
    public string toCity;  
    [XmlAttribute]  
    public bool isFirstClass;  
}  
<ServiceContract()>  
Public Interface IAirfareQuoteService  
    <OperationContract()>  
    <XmlSerializerFormat>  
    GetAirfare(itinerary as Itinerary, date as DateTime) as Double  
  
End Interface  
  
Class Itinerary  
  
    Public fromCity As String  
    Public toCity As String  
    <XmlSerializerFormat()>  
    Public isFirstClass As Boolean  
End Class  

자세한 내용은 XmlSerializer 클래스 사용을 참조하세요. 위 항목에 설명된 대로 수동으로 XmlSerializer로 전환할 특별한 이유가 없는 한 이 예제에서처럼 수동으로 전환하지 않는 것이 좋습니다.

.NET 매개 변수 이름을 계약 이름으로부터 격리시키려면 MessageParameterAttribute 특성을 사용하고, Name 속성을 사용하여 계약 이름을 설정합니다. 예를 들면, 다음 작업 계약은 이 항목의 첫 번째 예제에 해당합니다.

[OperationContract]  
public float GetAirfare(  
    [MessageParameter(Name="fromCity")] string originCity,  
    [MessageParameter(Name="toCity")] string destinationCity);  
<OperationContract()>  
  Function GetAirfare(<MessageParameter(Name := "fromCity")> fromCity As String, <MessageParameter(Name := "toCity")> toCity As String) As Double  

빈 메시지 설명

빈 요청 메시지는 입력 매개 변수나 참조 매개 변수를 사용하지 않고 설명할 수 있습니다. 예를 들어 C#의 경우:

[OperationContract]

public int GetCurrentTemperature();

예를 들어 Visual Basic의 경우 다음과 같습니다.

<OperationContract()>

Function GetCurrentTemperature() as Integer

빈 회신 메시지는 출력 또는 참조 매개 변수 없이 void 반환 형식을 사용하여 설명할 수 있습니다. 예:

[OperationContract]  
public void SetTemperature(int temperature);  
<OperationContract()>  
Sub SetTemperature(temperature As Integer)  

이것은 다음과 같은 단방향 연산과는 다릅니다.

[OperationContract(IsOneWay=true)]  
public void SetLightbulbStatus(bool isOn);  
<OperationContract(IsOneWay:=True)>  
Sub SetLightbulbStatus(isOne As Boolean)  

SetTemperatureStatus 연산은 빈 메시지를 반환합니다. 입력 메시지를 처리하는 데 문제가 있을 경우 대신 오류를 반환할 수도 있습니다. SetLightbulbStatus 연산은 아무 것도 반환하지 않습니다. 이 연산에서 오류 조건을 전달할 방법이 없습니다.

메시지 계약을 사용하여 메시지 설명

하나의 형식을 사용하여 전체 메시지를 나타내야 하는 경우가 있습니다. 이러한 목적을 위해 데이터 계약을 사용할 수는 있지만 메시지 계약을 사용하는 것이 좋습니다. 이렇게 하면 결과 XML에서 불필요한 래핑 수준이 생기지 않습니다. 또한 메시지 계약을 통해 결과 메시지를 보다 효과적으로 제어할 수 있습니다. 예를 들어 메시지 본문에 필요한 정보와 메시지 헤더에 필요한 사항을 결정할 수 있습니다. 다음 예제에서는 메시지 계약을 사용하는 방법을 보여 줍니다.

[ServiceContract]  
public interface IAirfareQuoteService  
{  
    [OperationContract]  
    GetAirfareResponse GetAirfare(GetAirfareRequest request);  
}  
  
[MessageContract]  
public class GetAirfareRequest  
{  
    [MessageHeader] public DateTime date;  
    [MessageBodyMember] public Itinerary itinerary;  
}  
  
[MessageContract]  
public class GetAirfareResponse  
{  
    [MessageBodyMember] public float airfare;  
    [MessageBodyMember] public string currency;  
}  
  
[DataContract]  
public class Itinerary  
{  
    [DataMember] public string fromCity;  
    [DataMember] public string toCity;  
}  
<ServiceContract()>  
Public Interface IAirfareQuoteService  
    <OperationContract()>  
    Function GetAirfare(request As GetAirfareRequest) As GetAirfareResponse  
End Interface  
  
<MessageContract()>  
Public Class GetAirfareRequest  
    <MessageHeader()>
    Public Property date as DateTime  
    <MessageBodyMember()>  
    Public Property itinerary As Itinerary  
End Class  
  
<MessageContract()>  
Public Class GetAirfareResponse  
    <MessageBodyMember()>  
    Public Property airfare As Double  
    <MessageBodyMember()> Public Property currency As String  
End Class  
  
<DataContract()>  
Public Class Itinerary  
    <DataMember()> Public Property fromCity As String  
    <DataMember()> Public Property toCity As String  
End Class  

자세한 내용은 메시지 계약 사용을 참조하세요.

앞의 예제의 경우 DataContractSerializer 클래스가 기본적으로 사용됩니다. XmlSerializer 클래스는 메시지 계약에 사용할 수도 있습니다. 이 작업을 수행하려면 XmlSerializerFormatAttribute 특성을 연산이나 계약에 적용하고 메시지 헤더와 본문 멤버의 XmlSerializer 클래스와 호환되는 형식을 사용합니다.

스트림을 사용하여 메시지 설명

연산에서 메시지를 설명하는 또 다른 방법은 Stream 클래스 또는 작업 계약의 파생 클래스 중 하나를 사용하거나 메시지 계약 본문 멤버(이 경우 유일한 멤버여야 함)로 사용하는 것입니다. 들어오는 메시지의 경우 형식은 Stream이어야 하며, 파생 클래스는 사용할 수 없습니다.

WCF는 serializer를 호출하지 않는 대신, 스트림에서 데이터를 검색하여 보내는 메시지에 직접 넣거나 들어오는 메시지에서 데이터를 검색하여 스트림에 직접 넣습니다. 다음 예제에서는 스트림의 사용 방법을 보여 줍니다.

[OperationContract]  
public Stream DownloadFile(string fileName);  
<OperationContract()>  
Function DownloadFile(fileName As String) As String  

하나의 메시지 본문에서 Stream과 비스트림 데이터를 결합할 수 없습니다. 메시지 헤더에 추가 데이터를 넣으려면 메시지 계약을 사용합니다. 다음 예제에서는 작업 계약을 정의할 때 잘못된 스트림 사용 방법을 보여 줍니다.

//Incorrect:  
// [OperationContract]  
// public void UploadFile (string fileName, Stream fileData);  
'Incorrect:  
    '<OperationContract()>  
    Public Sub UploadFile(fileName As String, fileData As StreamingContext)  

다음 샘플에서는 작업 계약을 정의할 때 올바른 스트림 사용 방법을 보여 줍니다.

[OperationContract]  
public void UploadFile (UploadFileMessage message);  
//code omitted  
[MessageContract]  
public class UploadFileMessage  
{  
    [MessageHeader] public string fileName;  
    [MessageBodyMember] public Stream fileData;  
}  
<OperationContract()>  
Public Sub UploadFile(fileName As String, fileData As StreamingContext)  
'Code Omitted  
<MessageContract()>  
Public Class UploadFileMessage  
   <MessageHeader()>  
    Public Property fileName As String  
    <MessageBodyMember()>  
    Public Property fileData As Stream  
End Class  

자세한 내용은 대용량 데이터 및 스트리밍을 참조하세요.

Message 클래스 사용

보내거나 받은 메시지를 프로그래밍 방식으로 완벽하게 제어하려면 다음 예제 코드에서처럼 Message 클래스를 직접 사용하면 됩니다.

[OperationContract]  
public void LogMessage(Message m);  
<OperationContract()>  
Sub LogMessage(m As Message)  

이러한 고급 시나리오는 메시지 클래스 사용에서 자세히 설명합니다.

오류 메시지 설명

반환 값과 출력 또는 참조 매개 변수를 사용하여 설명하는 메시지 이외에, 단방향이 아닌 연산은 적어도 두 개의 메시지, 즉 일반 응답 메시지와 오류 메시지를 반환할 수 있습니다. 다음 작업 계약을 예로 들 수 있습니다.

[OperationContract]  
float GetAirfare(string fromCity, string toCity, DateTime date);  
<OperationContract()>  
Function GetAirfare(fromCity As String, toCity As String, date as DateTime)  

이 연산은 float 숫자가 포함된 일반 메시지 또는 오류 코드 및 설명이 포함된 오류 메시지를 반환할 수 있습니다. 서비스 구현에서 FaultException을 throw하여 이 연산을 수행할 수 있습니다.

FaultContractAttribute 특성을 사용하여 가능한 추가 오류 메시지를 지정할 수 있습니다. 추가 오류는 다음 예제 코드에서처럼 DataContractSerializer를 사용하여 serialize할 수 있어야 합니다.

[OperationContract]  
[FaultContract(typeof(ItineraryNotAvailableFault))]  
float GetAirfare(string fromCity, string toCity, DateTime date);  
  
//code omitted  
  
[DataContract]  
public class ItineraryNotAvailableFault  
{  
    [DataMember]  
    public bool IsAlternativeDateAvailable;  
  
    [DataMember]  
    public DateTime alternativeSuggestedDate;  
}  
<OperationContract()>  
<FaultContract(GetType(ItineraryNotAvailableFault))>  
Function GetAirfare(fromCity As String, toCity As String, date as DateTime) As Double  
  
'Code Omitted  
<DataContract()>  
Public Class  
  <DataMember()>  
  Public Property IsAlternativeDateAvailable As Boolean  
  <DataMember()>  
  Public Property alternativeSuggestedDate As DateTime  
End Class  

이러한 추가 오류는 해당하는 데이터 계약 형식의 FaultException<TDetail>을 throw하여 생성될 수 있습니다. 자세한 내용은 예외 및 오류 처리를 참조하세요.

XmlSerializer 클래스를 사용하여 오류를 설명할 수 없습니다. XmlSerializerFormatAttribute는 오류 계약에 영향을 주지 않습니다.

파생 형식 사용

특정 연산 또는 메시지 계약에 기본 형식을 사용한 다음 실제로 연산을 호출할 때는 파생 형식을 사용해야 하는 경우가 있습니다. 이 경우 파생 형식을 사용할 수 있도록 ServiceKnownTypeAttribute 특성 또는 일부 대체 메커니즘을 사용해야 합니다. 다음과 같은 작업을 예로 들 수 있습니다.

[OperationContract]  
public bool IsLibraryItemAvailable(LibraryItem item);  
<OperationContract()>  
    Function IsLibraryItemAvailable(item As LibraryItem) As Boolean  

BookMagazine 이 두 형식이 LibraryItem에서 파생된다고 가정합니다. 이 형식을 IsLibraryItemAvailable 연산에서 사용하려면 다음과 같이 연산을 변경합니다.

[OperationContract]

[ServiceKnownType(typeof(Book))]

[ServiceKnownType(typeof(Magazine))]

public bool IsLibraryItemAvailable(LibraryItem item);

또는 다음 예제 코드에서처럼 기본 KnownTypeAttribute가 사용 중인 경우 DataContractSerializer 특성을 사용할 수 있습니다.

[OperationContract]  
public bool IsLibraryItemAvailable(LibraryItem item);  
  
// code omitted
  
[DataContract]  
[KnownType(typeof(Book))]  
[KnownType(typeof(Magazine))]  
public class LibraryItem  
{  
    //code omitted  
}  
<OperationContract()>  
Function IsLibraryItemAvailable(item As LibraryItem) As Boolean  
  
'Code Omitted  
<DataContract()>  
<KnownType(GetType(Book))>  
<KnownType(GetType(Magazine))>  
Public Class LibraryItem  
  'Code Omitted  
End Class  

XmlIncludeAttribute를 사용할 때 XmlSerializer 특성을 사용할 수 있습니다.

특정 연산 또는 전체 서비스에 ServiceKnownTypeAttribute 특성을 적용할 수 있습니다. 호출할 메서드의 형식이나 이름을 사용하여 KnownTypeAttribute 특성과 같은 알려진 형식 목록을 가져옵니다. 자세한 내용은 데이터 계약 알려진 형식을합니다.

사용 및 스타일 지정

WSDL(웹 서비스 기술 언어)을 사용하여 서비스를 설명하는 경우 문서 스타일과 RPC(원격 프로시저 호출) 스타일이 일반적으로 사용됩니다. 문서 스타일에서 전체 메시지 본문은 스키마를 사용하여 설명되고 WSDL은 해당 스키마 내의 요소를 참조하여 여러 메시지 본문 부분을 설명합니다. RPC 스타일에서 WSDL은 요소가 아닌 각 메시지 부분의 스키마 형식을 참조합니다. 이 두 스타일 중 하나를 수동으로 선택해야 하는 경우도 있습니다. 둘 중 하나만 수동으로 설정하려면 DataContractFormatAttribute가 사용 중인 경우에는 Style 특성을 적용한 다음 DataContractSerializer 속성을 설정하고, Style를 사용하는 경우에는 XmlSerializerFormatAttribute 특성에 XmlSerializer을 설정합니다.

또한 XmlSerializer는 serialize된 두 가지 형식의 XML LiteralEncoded를 지원합니다. Literal은 가장 일반적으로 허용되는 폼이며 DataContractSerializer에서 유일하게 지원하는 폼입니다. Encoded는 SOAP 사양의 5단원에 설명된 레거시 폼이며 새 서비스에는 사용하지 않는 것이 좋습니다. Encoded 모드로 전환하려면 Use 특성에서 XmlSerializerFormatAttribute 속성을 Encoded로 설정합니다.

대부분의 경우 StyleUse 속성에 대한 기본 설정을 변경하면 안 됩니다.

Serialization 프로세스 제어

여러 가지 방법으로 데이터를 serialize하는 방법을 사용자 지정할 수 있습니다.

서버 Serialization 설정 변경

기본 DataContractSerializer가 사용 중인 경우 ServiceBehaviorAttribute 특성을 서비스에 적용하여 서비스에서 serialization 프로세스의 몇 가지 특성을 제어할 수 있습니다. 특히 MaxItemsInObjectGraph 속성을 사용하여 DataContractSerializer가 역직렬화하는 개체의 최대 개수를 제한하는 할당량을 설정할 수도 있습니다. IgnoreExtensionDataObject 속성을 사용하여 라운드트립 버전 관리 기능을 해제할 수 있습니다. 할당량에 대한 자세한 내용은 데이터에 대한 보안 고려 사항을 참조하세요. 왕복에 대한 자세한 내용은 이후 버전과 호환되는 데이터 계약을 참조하세요.

[ServiceBehavior(MaxItemsInObjectGraph=100000)]  
public class MyDataService:IDataService  
{  
    public DataPoint[] GetData()  
    {  
       // Implementation omitted  
    }  
}  
<ServiceBehavior(MaxItemsInObjectGraph:=100000)>  
Public Class MyDataService Implements IDataService  
  
    Function GetData() As DataPoint()  
         ‘ Implementation omitted  
    End Function  
End Interface  

Serialization 동작

serializer가 특정 작업에 사용되고 있는지 여부에 따라 자동으로 연결되는 두 가지 동작, DataContractSerializerOperationBehaviorXmlSerializerOperationBehavior를 WCF에서 사용할 수 있습니다. 이러한 동작은 자동으로 적용되므로 일반적으로 사용자가 알아야 할 필요는 없습니다.

그러나 DataContractSerializerOperationBehavior에는 serialization 프로세스를 사용자 지정하는 데 사용할 수 있는 MaxItemsInObjectGraph, IgnoreExtensionDataObjectDataContractSurrogate 속성이 있습니다. 처음 두 속성은 앞 단원에서 설명한 것과 의미가 같습니다. DataContractSurrogate 속성을 사용하여 serialization 프로세스를 사용자 지정하고 확장하는 데 필요한 강력한 메커니즘인 데이터 계약 서로게이트를 사용하도록 설정할 수 있습니다. 자세한 내용은 데이터 계약 서로게이트를 참조하세요.

DataContractSerializerOperationBehavior를 사용하여 클라이언트와 서버 serialization 모두를 사용자 지정할 수 있습니다. 다음 예제에서는 클라이언트에 MaxItemsInObjectGraph 할당량을 늘리는 방법을 보여 줍니다.

ChannelFactory<IDataService> factory = new ChannelFactory<IDataService>(binding, address);  
foreach (OperationDescription op in factory.Endpoint.Contract.Operations)  
{  
    DataContractSerializerOperationBehavior dataContractBehavior =  
                op.Behaviors.Find<DataContractSerializerOperationBehavior>()  
                as DataContractSerializerOperationBehavior;  
    if (dataContractBehavior != null)  
    {  
        dataContractBehavior.MaxItemsInObjectGraph = 100000;  
    }  
}  
IDataService client = factory.CreateChannel();  
Dim factory As ChannelFactory(Of IDataService) = New ChannelFactory(Of IDataService)(binding, address)  
For Each op As OperationDescription In factory.Endpoint.Contract.Operations  
        Dim dataContractBehavior As DataContractSerializerOperationBehavior = op.Behaviors.Find(Of DataContractSerializerOperationBehavior)()  
        If dataContractBehavior IsNot Nothing Then  
            dataContractBehavior.MaxItemsInObjectGraph = 100000  
        End If  
     Next  
    Dim client As IDataService = factory.CreateChannel  

다음은 자체 호스팅된 경우 서비스의 해당 코드입니다.

ServiceHost serviceHost = new ServiceHost(typeof(IDataService))  
foreach (ServiceEndpoint ep in serviceHost.Description.Endpoints)  
{  
foreach (OperationDescription op in ep.Contract.Operations)  
{  
        DataContractSerializerOperationBehavior dataContractBehavior =  
           op.Behaviors.Find<DataContractSerializerOperationBehavior>()  
                as DataContractSerializerOperationBehavior;  
        if (dataContractBehavior != null)  
        {  
            dataContractBehavior.MaxItemsInObjectGraph = 100000;  
        }  
}  
}  
serviceHost.Open();  
Dim serviceHost As ServiceHost = New ServiceHost(GetType(IDataService))  
        For Each ep As ServiceEndpoint In serviceHost.Description.Endpoints  
            For Each op As OperationDescription In ep.Contract.Operations  
                Dim dataContractBehavior As DataContractSerializerOperationBehavior = op.Behaviors.Find(Of DataContractSerializerOperationBehavior)()  
  
                If dataContractBehavior IsNot Nothing Then  
                    dataContractBehavior.MaxItemsInObjectGraph = 100000  
                End If  
            Next  
        Next  
        serviceHost.Open()  

웹 호스팅의 경우 새 ServiceHost 파생 클래스를 만들고 서비스 호스트 팩터리를 사용하여 연결해야 합니다.

구성에서 Serialization 설정 제어

ph x="1" /> 및 IgnoreExtensionDataObject는 다음 예제에서처럼 dataContractSerializer 엔드포인트 또는 서비스 동작을 사용하여 구성을 통해 제어될 수 있습니다.

<configuration>  
    <system.serviceModel>  
        <behaviors>  
            <endpointBehaviors>  
                <behavior name="LargeQuotaBehavior">  
                    <dataContractSerializer  
                      maxItemsInObjectGraph="100000" />  
                </behavior>  
            </endpointBehaviors>  
        </behaviors>  
        <client>  
            <endpoint address="http://example.com/myservice"  
                  behaviorConfiguration="LargeQuotaBehavior"  
                binding="basicHttpBinding" bindingConfiguration=""
                            contract="IDataService"  
                name="" />  
        </client>  
    </system.serviceModel>  
</configuration>  

공유 형식 Serialization, 개체 그래프 유지 및 사용자 지정 Serializer

DataContractSerializer는 .NET 형식 이름이 아니라 데이터 계약 이름을 사용하여 serialize합니다. 이러한 serialization 방식은 서비스 기반 아키텍처 개념과 일치하며, 연결 계약에 영향을 주지 않고 .NET 형식을 변경할 수 있는 등 유연성을 높여 줍니다. 드문 경우지만 실제 .NET 형식 이름을 serialize해야 하는 경우가 있으며, 이 경우 .NET Framework Remoting 기술과 유사한 클라이언트와 서버 간 밀접한 결합이 가능합니다. 일반적으로 .NET Framework Remoting에서 WCF로 마이그레이션할 때 사용하는 드문 경우를 제외하고 이 방식은 권장되지 않습니다. 이 경우에는 NetDataContractSerializer 클래스 대신 DataContractSerializer 클래스를 사용해야 합니다.

DataContractSerializer는 일반적으로 개체 그래프를 개체 트리로 serialize합니다. 즉, 같은 개체를 두 번 이상 참조하는 경우 두 번 이상 serialize됩니다. PurchaseOrderbillTo라고 하는 두 가지 주소 형식 필드가 있는 shipTo 인스턴스를 예로 들 수 있습니다. 두 필드가 같은 주소 인스턴스로 설정된 경우 serialization 및 deserialization 후 두 개의 동일한 주소 인스턴스가 생깁니다. XmlSerializerStyle에 대해 앞 단원에서 설명한 대로 Use에서 사용할 수 있는 레거시 SOAP 인코딩 표준을 제외하고, XML로 개체 그래프를 나타낼 표준 상호 운용 가능한 방법이 없기 때문에 이와 같이 수행됩니다. 개체 그래프를 트리로 serialize하면 순환 참조가 있는 그래프를 serialize할 수 없는 등의 단점이 있습니다. 상호 운용이 가능하지 않아도 실제 개체 그래프 serialization으로 전환해야 하는 경우도 있습니다. 이 작업은 DataContractSerializer로 설정된 preserveObjectReferences 매개 변수를 사용하여 생성된 true를 사용하여 수행할 수 있습니다.

기본 제공 serializer가 사용자 시나리오에 적합하지 않은 경우도 있습니다. 대부분의 경우 XmlObjectSerializerDataContractSerializer가 모두 파생된 NetDataContractSerializer 추상화를 사용할 수 있습니다.

앞의 세 가지 경우(.NET 형식 유지, 개체 그래프 유지 및 XmlObjectSerializer 기반의 완전한 사용자 지정 serialization) 모두 사용자 지정 serializer를 연결해야 합니다. 그렇게 하려면 다음 단계를 수행합니다.

  1. DataContractSerializerOperationBehavior에서 파생되는 고유한 동작을 작성합니다.

  2. 두 개의 CreateSerializer 메서드를 재정의하여 고유한 serializer(NetDataContractSerializer, DataContractSerializerpreserveObjectReferences로 설정된 true 또는 사용자 지정 XmlObjectSerializer)를 반환합니다.

  3. 서비스 호스트를 열거나 클라이언트 채널을 만들기 전에 기존 DataContractSerializerOperationBehavior 동작을 제거하고 이전 단계에서 만든 사용자 지정 파생 클래스에 연결합니다.

고급 serialization 개념에 대한 자세한 내용은 Serialization 및 Deserialization을 참조하세요.

참고 항목