类映射
概述
在本指南中,您可以了解如何自定义 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
后跟方法所应用的属性名。当驱动程序看到具有此命名约定的方法时,它将使用该方法来确定是否序列化具有提供属性名的属性。
以下示例创建了一个方法,只有当 Age
属性的值不等于 0
时才序列化它。驱动程序不会序列化任何不满足此要求的属性。
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# 类的更多信息,请参阅 POCOs。