类映射
Overview
在本指南中,您可以了解如何自定义 MongoDB .NET/C# 驱动程序将 BSON 文档与 C# 类进行映射的方式。请阅读此页面了解有关默认类映射行为的更多信息,或者是否需要自定义驱动程序序列化或反序列化数据的方式。
自动类映射
当您使用类而非 BsonDocument
表示MongoDB集合中的数据时,.NET/C#驱动程序会自动创建一个类映射,用于序列化或反序列化您的数据。它通过将文档中的字段名称与类中的属性名称进行匹配来完成此映射。
重要
类中属性的类型应与文档中字段的类型匹配。.NET/C# 驱动程序根据类中属性的类型实例化序列化器。如果在驱动程序尝试反序列化数据时类型不匹配,则序列化器就会抛出异常。
手动创建类映射
您可以绕过驱动程序的自动类映射功能,并使用 RegisterClassMap()
方法手动定义类映射。
以下示例定义 Person
类:
public class Person { public string Name { get; set; } public int Age { get; set; } public List<string> Hobbies {get; set;} }
以下代码演示如何注册 Person
类的类映射:
BsonClassMap.RegisterClassMap<Person>(classMap => { classMap.MapMember(p => p.Name); classMap.MapMember(p => p.Age); classMap.MapMember(p => p.Hobbies); });
重要
您必须先注册类映射,然后 才能在代码中使用它。我们建议在初始化与 MongoDB 的连接之前注册类映射。
您还可以手动映射类属性的子集,同时仍允许驱动程序自动映射其余属性。为此,注册类映射并调用 AutoMap()
方法,然后再手动指定属性。
在以下代码示例中,AutoMap()
方法映射 Person
类的所有属性,然后手动调整 Hobbies
字段的映射:
BsonClassMap.RegisterClassMap<Person>(classMap => { classMap.AutoMap(); classMap.MapMember(p => p.Hobbies).SetElementName("favorite_hobbies"); });
自定义类序列化
您可以通过使用类的属性或在注册类映射时调用方法来自定义驱动程序在类级别序列化和反序列化文档的方式。
忽略额外元素
当 BSON 文档反序列化为 C# 类时,.NET/C# 驱动程序会查看文档中每个字段的名称,并尝试在类中查找匹配的属性名称。默认情况下,如果文档中的字段在类中没有匹配项,驱动程序会抛出异常。
您可以使用 BsonIgnoreExtraElements
属性选择忽略任何没有匹配类属性的元素。这样可以防止驱动程序抛出异常,并映射具有匹配类属性的任何其他字段。
以下示例显示如何将 BsonIgnoreExtraElements
属性添加至类。
[ ]public class Person { public string Name { get; set; } public int Age { get; set; } public List<string> Hobbies {get; set;} }
您还可以在注册类映射时忽略任何额外元素:
BsonClassMap.RegisterClassMap<Person>(classMap => { classMap.AutoMap(); classMap.SetIgnoreExtraElements(true); });
使用构造函数映射
默认情况下,仅当类具有不带参数的构造函数时,.NET/C# 驱动程序才能自动映射该类。如果想要驱动程序使用接受一个或多个参数的构造函数,您可以将 BsonConstructor
属性添加到该构造函数中。在这种情况下,驱动程序会检查类型以确定如何将构造函数参数映射到类属性或字段。
当驱动程序为以下 Person
类创建类映射时,它将使用标有 BsonConstructor
属性的构造函数。name
参数将映射到 Name
属性,并且 age
参数将映射到 Age
属性。
public class Person { public string Name { get; set; } public int Age { get; set; } public List<string> Hobbies {get; set;} [ ] public Person(string name, string age) { Name = name; Age = age; } }
提示
多个 BsonConstructor 属性
如果存在多个具有 BsonConstructor
属性的构造函数,则驱动程序将使用具有与文档中匹配字段的最多参数的构造函数。
您还可以指定注册类映射时要使用的构造函数:
public class Person { public string Name { get; set; } public int Age { get; set; } public List<string> Hobbies {get; set;} public Person(string name, string age) { Name = name; Age = age; } } BsonClassMap.RegisterClassMap<Person>(classMap => { classMap.AutoMap(); classMap.MapCreator(p => new Person(p.Name, p.Age)); });
自定义属性序列化
您可以通过向类属性中添加多个属性来自定义驱动程序序列化类属性的方式。有关自定义属性序列化的更多信息,请参阅 自定义序列化。
支持额外元素
您可以设计 C# 类来存储文档中没有匹配类属性的任何额外元素。为此,您的类必须具有 BsonDocument
类型属性以保存额外的元素。
以下代码使用带有 ExtraElements
类属性的 BsonExtraElements
属性来指示驱动程序存储额外元素:
public class Person { public string Name { get; set; public int Age { get; set; } public List<string> Hobbies {get; set;} [ ] public BsonDocument ExtraElements {get; set;} }
在初始化类映射时,还可以支持额外元素,如下所示:
BsonClassMap.RegisterClassMap<Person>(classMap => { classMap.AutoMap(); classMap.MapExtraElementsMember(p => p.ExtraElements); });
注意
驱动程序将带有额外元素的类序列化回 BSON 后,额外元素的顺序可能与原始文档中的顺序不同。
动态序列化属性
您可以使用某个方法来确定是否序列化属性。为了使驱动程序在序列化时自动使用该方法,必须在方法名称前加上 ShouldSerialize
作为前缀,然后是该方法适用的属性的名称。当驱动程序看到具有此命名规范的方法时,它会使用该方法来确定是否序列化具有所提供的属性名称的属性。
以下示例创建一个仅在其值不等于 0
时序列化 Age
属性的方法。驱动程序不会序列化其值不满足此要求的任何属性:
public class Person { public string Name { get; set; } public int Age { get; set; } public List<string> Hobbies {get; set;} public bool ShouldSerializeAge() { return Age != 0; } }
您还可以在注册类映射时指定方法:
BsonClassMap.RegisterClassMap<Employee>(classMap => { classMap.AutoMap(); classMap.MapMember(p => c.Age).SetShouldSerializeMethod( obj => ((Person) obj).Age != 0 ); });
更多信息
有关使用 C# 类的更多信息,请参阅 POCO。