다음을 통해 공유


데이터 계약 알려진 형식

KnownTypeAttribute 클래스를 사용하면 고려 사항에 포함해야 하는 형식을 deserialization을 수행하는 동안 미리 지정할 수 있습니다. 작업 예제는 Known Types 예제를 참조하십시오.

일반적으로 클라이언트와 서비스 간에 매개 변수와 반환 값을 전달할 때 두 끝점은 전송할 데이터의 모든 데이터 계약을 공유합니다. 그러나 다음과 같은 경우는 그렇지 않습니다.

  • 보낸 데이터 계약은 필요한 데이터 계약에서 파생됩니다. 자세한 내용은 데이터 계약 동등성의 상속에 대한 단원을 참조하십시오. 이 경우 전송한 데이터에는 수신하는 끝점에서 필요한 것과 동일한 데이터 계약이 없습니다.
  • 전송할 정보에 대해 선언된 형식은 클래스, 구조체 또는 열거형이 아니라 인터페이스입니다. 따라서 인터페이스를 구현하는 형식을 실제로 보냈는지 미리 알 수 없으므로 수신하는 끝점에서 전송된 데이터에 대한 데이터 계약을 미리 확인할 수 없습니다.
  • 전송할 정보에 대해 선언된 형식은 Object입니다. 모든 형식은 Object에서 상속되며 실제로 보낸 형식을 미리 알 수 없으므로 수신하는 끝점에서 전송된 데이터에 대한 데이터 계약을 미리 확인할 수 없습니다. 이것은 첫 번째 항목의 특별한 경우입니다. 모든 데이터 계약은 Object에 대해 생성되는 빈 데이터 계약인 기본값에서 파생됩니다.
  • .NET Framework 형식을 비롯한 일부 형식에는 앞의 세 범주 중 하나에 있는 멤버가 포함됩니다. 예를 들어 HashtableObject를 사용하여 해시 테이블에 실제 개체를 저장합니다. 이러한 형식을 serialize할 때 받는 쪽에서 이러한 멤버에 대한 데이터 계약을 미리 확인할 수 없습니다.

KnownTypeAttribute 클래스

데이터가 수신하는 끝점에 도착하면 WCF 런타임에서는 CLR(공용 언어 런타임) 형식의 인스턴스로 데이터를 deserialize하려고 시도합니다. deserialization을 위해 인스턴스화되는 형식은 메시지 내용이 따르는 데이터 계약을 확인하도록 들어오는 메시지를 먼저 검사하여 선택됩니다. 그런 다음 deserialization 엔진은 메시지 내용과 호환되는 데이터 계약을 구현하는 CLR 형식을 찾습니다. 이 프로세스 중에 deserialization 엔진에서 허용하는 후보 형식 집합을 deserializer의 "알려진 형식" 집합이라고 합니다.

deserialization 엔진에 형식을 알리는 한 가지 방법은 KnownTypeAttribute를 사용하는 것입니다. 특성은 개별 데이터 멤버에 적용될 수 없고 전체 데이터 계약 형식에만 적용될 수 있습니다. 특성은 클래스 또는 구조체일 수 있는 외부 형식에 적용됩니다. 가장 기본적인 사용법에서 특성을 적용하면 형식이 "알려진 형식"으로 지정됩니다. 이렇게 하면 외부 형식의 개체 또는 해당 멤버를 통해 참조되는 개체가 deserialize될 때마다 알려진 형식이 알려진 형식 집합의 일부가 됩니다. 두 개 이상의 KnownTypeAttribute 특성을 같은 형식에 적용할 수 있습니다.

알려진 형식 및 기본 형식

기본 형식과 기본 형식으로 처리되는 특정 형식(예: DateTimeXmlElement)은 항상 "알려진" 형식이므로 이 메커니즘을 통해 추가되지 않아도 됩니다. 그러나 기본 형식 배열은 명시적으로 추가되어야 합니다. 대부분의 컬렉션은 배열과 동일한 것으로 간주됩니다. 제네릭이 아닌 컬렉션은 Object의 배열과 동일한 것으로 간주됩니다. 기본 형식, 기본 배열 및 기본 컬렉션 사용 예제는 예제 4를 참조하십시오.

참고

다른 기본 형식과 달리 DateTimeOffset 구조체는 기본적으로 알려진 형식이 아니므로 이 형식을 알려진 형식 목록에 수동으로 추가해야 합니다.

예제

다음 예제에서는 사용 중인 KnownTypeAttribute 클래스를 보여 줍니다.

예제 1

상속 관계가 있는 세 클래스가 있습니다.

ShapeOfLogo 멤버가 CircleType 또는 TriangleType 개체로 설정된 경우 deserialization 엔진이 데이터 계약 이름 "Circle" 또는 "Triangle"을 포함하는 형식을 인식하지 않으므로 다음 CompanyLogo 클래스를 serialize할 수 있지만 deserialize할 수는 없습니다.

CompanyLogo 형식을 쓰는 올바른 방법은 다음 코드에 나와 있습니다.

외부 형식 CompanyLogo2가 deserialize될 때마다 deserialization 엔진이 CircleTypeTriangleType에 대해 알고 있으므로, "Circle" 및 "Triangle" 데이터 계약에 일치하는 형식을 찾을 수 있습니다.

예제 2

다음 예제에서 CustomerTypeACustomerTypeB에 모두 Customer 데이터 계약이 있어도 CustomerTypeB만 deserialization 엔진에 알려지므로 PurchaseOrder가 deserialize될 때마다 CustomerTypeB의 인스턴스가 만들어집니다.

예제 3

다음 예제에서 Hashtable은 해당 콘텐츠를 내부적으로 Object로 저장합니다. 해시 테이블을 성공적으로 deserialize하려면 deserialization 엔진이 해시 테이블에서 발생할 수 있는 가능한 형식 집합을 알고 있어야 합니다. 이 경우 BookMagazine 개체만 Catalog에 저장되므로 이러한 개체가 KnownTypeAttribute 특성을 사용하여 추가된다는 것을 미리 알고 있습니다.

예제 4

다음 예제에서 데이터 계약은 숫자와 숫자에 수행할 작업을 저장합니다. Numbers 데이터 멤버는 정수, 정수 배열 또는 정수를 포함하는 List일 수 있습니다.

이것은 응용 프로그램 코드입니다.

알려진 형식, 상속 및 인터페이스

알려진 형식이 KnownTypeAttribute 특성을 사용하여 특정 형식과 연결되면 이 알려진 형식은 해당 형식의 모든 파생 형식과도 연결됩니다. 예를 들어 다음과 같은 코드를 참조하십시오.

AdditionalShape 필드에서 SquareCircle을 사용할 KnownTypeAttribute 특성이 기본 클래스(Drawing)에 이미 적용되었기 때문에 DoubleDrawing 클래스에는 이러한 특성이 필요하지 않습니다.

알려진 형식은 인터페이스가 아닌 클래스와 구조체에만 연결할 수 있습니다.

개방형 제네릭 메서드를 사용한 알려진 형식

제네릭 형식을 알려진 형식으로 추가해야 할 수 있습니다. 하지만 개방형 제네릭 형식은 KnownTypeAttribute 특성에 대한 매개 변수로 전달될 수 없습니다.

이 문제는 대체 메커니즘을 사용하여 해결할 수 있습니다. 알려진 형식 컬렉션에 추가할 형식 목록을 반환하는 메서드를 작성합니다. 그런 다음 몇 가지 제한 사항으로 인해 이 메서드 이름이 KnownTypeAttribute 특성에 대한 문자열 인수로 지정됩니다.

이 메서드는 KnownTypeAttribute 특성이 적용되는 형식에 있어야 하고, static 메서드여야 하며, 매개 변수를 취하지 않아야 하고, TypeIEnumerable에 할당될 수 있는 개체를 반환해야 합니다.

KnownTypeAttribute 특성을 메서드 이름과 결합하거나 KnownTypeAttribute 특성을 같은 형식의 실제 형식과 결합할 수 없습니다. 또한 메서드 이름이 있는 두 개 이상의 KnownTypeAttribute를 같은 형식에 적용할 수 없습니다.

다음 클래스를 참조하십시오.

theDrawing 필드에는 제네릭 클래스 BlackAndWhiteDrawing과 제네릭 클래스 ColorDrawing의 인스턴스가 포함되어 있으며, 모두 제네릭 클래스 Drawing에서 상속됩니다. 일반적으로 두 클래스 모두 알려진 형식에 추가해야 하지만 다음 예제는 올바른 특성 구문이 아닙니다.

// Invalid syntax for attributes:
// [KnownType(typeof(ColorDrawing<T>))]
// [KnownType(typeof(BlackAndWhiteDrawing<T>))]
' Invalid syntax for attributes:
' <KnownType(GetType(ColorDrawing(Of T))), _
' KnownType(GetType(BlackAndWhiteDrawing(Of T)))>

그러므로 이러한 형식을 반환할 메서드를 만들어야 합니다. 이 형식을 쓰는 올바른 방법은 다음 코드에 나와 있습니다.

알려진 형식을 추가하는 다른 방법

DataContractSerializerKnownTypes 속성을 통해 액세스한 ReadOnlyCollection에 형식을 추가할 수도 있습니다.

또한 구성 파일을 통해 알려진 형식을 추가할 수 있습니다. 이 기능은 WCF(Windows Communication Foundation)에 타사 형식 라이브러리를 사용할 때처럼 적합한 deserialization에 알려진 형식이 필요한 형식을 제어하지 않을 때 유용합니다.

다음 구성 파일에서는 구성 파일에 알려진 형식을 지정하는 방법을 보여 줍니다.

<configuration>

<system.runtime.serialization>

<dataContractSerializer>

<declaredTypes>

<add type="MyCompany.Library.Shape,

MyAssembly, Version=2.0.0.0, Culture=neutral,

PublicKeyToken=XXXXXX, processorArchitecture=MSIL">

<knownType type="MyCompany.Library.Circle,

MyAssembly, Version=2.0.0.0, Culture=neutral,

PublicKeyToken=XXXXXX, processorArchitecture=MSIL"/>

</add>

</declaredTypes>

</dataContractSerializer>

</system.runtime.serialization>

</configuration>

앞의 구성 파일에서는 MyCompany.Library.Shape라는 데이터 계약 형식이 MyCompany.Library.Circle을 알려진 형식으로 포함하도록 선언되었습니다.

참고 항목

참조

KnownTypeAttribute
Hashtable
Object
DataContractSerializer
KnownTypes

개념

데이터 계약 동등성

기타 리소스

Known Types