Docs Menu
Docs Home
/ / /
C#/.NET
/ /

다형성 객체

이 페이지의 내용

  • 개요
  • 다형성 객체 역직렬화하기
  • 판별자 사용
  • 스칼라 판별자 규칙
  • HierarchicalDiscriminatorConvention
  • 사용자 지정 판별자 규칙

다형성 객체는 하나 이상의 상위 클래스로부터 속성과 메서드를 상속받습니다. 이러한 객체는 .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] 특성을 적용하는 방법을 보여 줍니다.

[BsonKnownTypes(typeof(Cat), typeof(Dog))]
public class Animal
{
}
[BsonKnownTypes(typeof(Lion), typeof(Tiger))]
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을 사용할 수 있습니다. 이 규칙에 따르면 _t 값은 문서 유형의 상속 계층 구조에 있는 모든 클래스의 배열입니다.

HierarchicalDiscriminatorConvention을 사용하려면 상속 계층 구조의 기본 클래스에 루트 클래스로 레이블을 지정합니다. automapper를 사용하는 경우 [BsonDiscriminatorAttribute] 특성을 클래스에 적용하고 RootClass = true를 인수로 전달하여 루트 클래스에 레이블을 지정합니다. 다음 코드 예시에서는 Animal 클래스에 예제 상속 계층 구조의 루트로 레이블을 지정합니다.

[BsonDiscriminator(RootClass = true)]
[BsonKnownTypes(typeof(Cat), typeof(Dog)]
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'로 설정합니다.

[BsonDiscriminator("myAnimalClass")]
public class Animal
{
}

클래스 맵을 수동으로 만드는 경우 SetDiscriminator() 메서드를 호출하고 클래스 맵을 등록할 때 사용자 지정 판별자 값을 인수로 전달합니다. 다음 코드 예제에서는 Animal 클래스의 판별자 필드 값을 "myAnimalClass"로 설정합니다.

BsonClassMap.RegisterClassMap<Animal>(classMap =>
{
classMap.AutoMap();
classMap.SetDiscriminator("myAnimalClass");
});

직렬화 후 이전 Animal 클래스의 인스턴스는 다음과 같이 나타납니다.

{ "_id": "...", "_t": "myAnimalClass"}

돌아가기

POCO