다형성 객체
개요
다형성 객체는 하나 이상의 상위 클래스로부터 속성과 메서드를 상속받습니다. 이러한 객체는 .NET/C# 드라이버가 BSON 문서와 올바르게 직렬화할 수 있도록 하기 위해 특수 매핑을 요구합니다.
이 가이드에서는 다음에 대해 설명합니다.
다형성 유형을 역직렬화하는 방법
.NET/C# 드라이버에 포함된 판별자 규칙
사용자 지정 판별자 규칙을 만드는 방법
이 페이지의 예시에서는 다음과 같은 상속 계층 구조를 사용합니다.
public class Animal { } public class Cat : Animal { } public class Dog : Animal { } public class Lion : Cat { } public class Tiger : Cat { }
다형성 객체 역직렬화하기
직렬 변환기가 다형성 객체를 역직렬화하려면 먼저 상속 계층 구조에 있는 모든 클래스의 관계를 문서화해야 합니다.
자동 매퍼를 사용하여 클래스를 매핑하는 경우 계층 구조의 각 기본 클래스에 [BsonKnownTypes]
속성을 적용합니다. 기본 클래스에서 직접 상속되는 각 클래스를 인수로 전달합니다.
다음 예시는 예시 Animal
계층 구조의 클래스에 [BsonKnownTypes]
특성을 적용하는 방법을 보여 줍니다.
[ ]public class Animal { } [ ]public class Cat : Animal { } public class Dog : Animal { } public class Lion : Cat { } public class Tiger : Cat { }
참고
BsonKnownTypes 사용
상위 클래스에만 [BsonKnownTypes]
특성을 적용합니다. 계층 구조의 모든 하위 클래스가 아닌 클래스에서 직접 상속하는 유형만 인수로 전달합니다.
클래스 맵을 수동으로 만드는 경우 다음 예시와 같이 계층 구조의 모든 클래스에 대해 BsonClassMap.RegisterClassMap<T>()
메서드를 호출합니다.
BsonClassMap.RegisterClassMap<Animal>(); BsonClassMap.RegisterClassMap<Cat>(); BsonClassMap.RegisterClassMap<Dog>(); BsonClassMap.RegisterClassMap<Lion>(); BsonClassMap.RegisterClassMap<Tiger>();
판별자 사용
MongoDB에서 판별 자는 문서가 역직렬화하는 클래스를 식별하기 위해 문서에 추가되는 필드입니다. collection에 단일 상속 계층 구조의 유형이 두 개 이상 포함된 경우 판별자는 각 document가 올바른 클래스로 역직렬화되는지 확인합니다. .NET/C# 드라이버는 BSON 문서의 _t
필드에 판별자 값을 저장합니다. 일반적으로 _t
은 BSON 문서에서 _id
다음으로 두 번째 필드입니다.
판별자 규칙은 판별자 필드에 저장된 값을 정의합니다. 이 섹션에서는 .NET/C# 드라이버와 함께 포함된 판별자 규칙과 사용자 지정 판별자 규칙을 만드는 방법에 대해 알아볼 수 있습니다.
스칼라 판별자 규칙
기본적으로 .NET/C# 드라이버는 ScalarDiscriminatorConvention
을 사용합니다. 이 규칙에 따라 .NET/C# 드라이버는 _t
필드의 값을 문서가 직렬화된 클래스의 이름으로 설정합니다.
예시 Animal
클래스와 각 하위 클래스의 인스턴스를 만든다고 가정합니다. 이러한 객체를 단일 컬렉션으로 직렬화하는 경우 .NET/C# 드라이버는 ScalarDiscriminatorConvention
(을)를 적용하고 해당 BSON 문서는 다음과 같이 표시됩니다.
{ _id: ..., _t: "Animal", ... } { _id: ..., _t: "Cat", ... } { _id: ..., _t: "Dog", ... } { _id: ..., _t: "Lion", ... } { _id: ..., _t: "Tiger", ... }
ScalarDiscriminatorConvention
은 간결한 판별자 값을 사용하지만 쿼리를 실행하기 어려울 수 있습니다. 예를 들어 유형 또는 하위 유형이 Cat
인 모든 문서를 찾으려면 찾고 있는 각 클래스를 명시적으로 나열해야 합니다.
var query = coll.AsQueryable().Where( item => item.GetType() == typeof(Cat) || item.GetType() == typeof(Lion) || item.GetType() == typeof(Tiger));
참고
OfType<T>() 및 is 연산자
스칼라 판별자의 유형을 확인할 때는 앞의 코드 예시 에 표시된 Where
구문을 사용합니다. Aggregate().OfType<T>()
메서드를 사용하려고 하거나 is
연산자 가 포함된 표현식 을 Aggregate().Match()
메서드에 전달하면 운전자 에서 예외가 발생합니다.
HierarchicalDiscriminatorConvention
다형성 유형 컬렉션에 대한 쿼리를 단순화하기 위해 HierarchicalDiscriminatorConvention
을 사용할 수 있습니다. 이 규칙에 따르면 _t
값은 문서 유형의 상속 계층 구조에 있는 모든 클래스의 배열입니다.
HierarchicalDiscriminatorConvention
을 사용하려면 상속 계층 구조의 기본 클래스에 루트 클래스로 레이블을 지정합니다. automapper를 사용하는 경우 [BsonDiscriminatorAttribute]
특성을 클래스에 적용하고 RootClass = true
를 인수로 전달하여 루트 클래스에 레이블을 지정합니다. 다음 코드 예시에서는 Animal
클래스에 예제 상속 계층 구조의 루트로 레이블을 지정합니다.
[ ][ ]public class Animal { }
클래스 맵을 수동으로 생성하는 경우 루트 클래스에 대한 클래스 맵을 등록할 때 SetIsRootClass()
메서드를 호출하고 true
를 인수로 전달하세요. 다음 코드 예시는 5개의 예시 클래스 모두에 대한 클래스 맵을 등록하지만 Animal
클래스만 상속 계층 구조의 루트로 표시합니다.
BsonClassMap.RegisterClassMap<Animal>(classMap => { classMap.AutoMap(); classMap.SetIsRootClass(true); }); BsonClassMap.RegisterClassMap<Cat>(); BsonClassMap.RegisterClassMap<Dog>(); BsonClassMap.RegisterClassMap<Lion>(); BsonClassMap.RegisterClassMap<Tiger>();
예시 Animal
클래스를 상속 계층 구조 루트로 레이블을 지정한 후 Animal
클래스와 각 하위 클래스의 인스턴스를 만든다고 가정해 보겠습니다. 이러한 객체를 단일 컬렉션으로 직렬화하는 경우, .NET/C# 드라이버는 HierarchicalDiscriminatorConvention
을 적용하고 여기에 해당하는 BSON 문서는 다음과 같이 표시됩니다.
{ _id: ..., _t: "Animal", ... } { _id: ..., _t: ["Animal", "Cat"], ... } { _id: ..., _t: ["Animal", "Dog"], ... } { _id: ..., _t: ["Animal", "Cat", "Lion"], ... } { _id: ..., _t: ["Animal", "Cat", "Tiger"], ... }
중요
루트 클래스 판별자
루트 클래스에 매핑된 모든 문서는 여전히 판별자 필드에 문자열 값을 사용합니다.
HierarchicalDiscriminatorConvention
을 사용하면 다음 예시와 같이 단일 부울 조건을 사용하여 유형 또는 하위 유형이 Cat
인 모든 문서를 검색할 수 있습니다.
var query = coll.Aggregate().Match(a => a is Cat);
사용자 지정 판별자 규칙
.NET/C# 드라이버에서 사용하는 규칙을 따르지 않는 데이터로 작업하는 경우(예: 다른 드라이버 또는 객체 매퍼를 통해 MongoDB에 삽입된 데이터), 클래스가 이러한 규칙에 부합하도록 하기 위해 판별자 필드에 다른 값을 사용해야 할 수 있습니다.
자동 매퍼를 사용하는 경우 클래스에 [BsonDiscriminator]
특성을 적용하고 사용자 지정 판별자 값을 문자열 인수로 전달하여 클래스의 판별자 필드에 사용자 지정 값을 지정할 수 있습니다. 다음 코드 예제에서는 Animal
클래스의 판별자 필드 값을 'myAnimalClass'로 설정합니다.
[ ]public class Animal { }
클래스 맵을 수동으로 만드는 경우 SetDiscriminator()
메서드를 호출하고 클래스 맵을 등록할 때 사용자 지정 판별자 값을 인수로 전달합니다. 다음 코드 예제에서는 Animal
클래스의 판별자 필드 값을 "myAnimalClass"로 설정합니다.
BsonClassMap.RegisterClassMap<Animal>(classMap => { classMap.AutoMap(); classMap.SetDiscriminator("myAnimalClass"); });
직렬화 후 이전 Animal
클래스의 인스턴스는 다음과 같이 나타납니다.
{ "_id": "...", "_t": "myAnimalClass"}