MongoDB C#:泛型注册类映射正常,直接用类型注册失效
问题:MongoDB C#驱动非泛型注册类映射仅序列化接口成员
我有一组对象,每个对象都包含EventData属性,该属性对应多种继承自IEventData接口的类型,示例文档结构如下:
{ _id: '...', EventData: { _t: 'TypeA', ... } } { _id: '...', EventData: { _t: 'TypeB', ... } }
使用泛型版本注册类映射时,EventData能正确序列化所有属性和类型鉴别器:
BsonClassMap.RegisterClassMap<TypeA>(); // 写入集合的完整数据 // { _id: '...', EventData: { _t: 'TypeA', InterfaceProperty: '...', ClassProperty: '...' } }
但因为事件类型数量多,我尝试用反射自动化注册:遍历所有实现IEventData的类型,使用非泛型方式注册类映射,结果仅序列化了接口成员:
var types = AppDomain.CurrentDomain.GetAssemblies() .SelectMany(i => i.GetTypes()) .Where(t => typeof(IEventData).IsAssignableFrom(t)); foreach (var type in types) { // 跳过接口 if (type.IsInterface) continue; if (!BsonClassMap.IsClassMapRegistered(type)) BsonClassMap.RegisterClassMap(new BsonClassMap(type)); } // 仅接口属性被写入 // { _id: '...', EventData: { _t: 'TypeA', InterfaceProperty: '...' } }
请问非泛型方式注册类映射时,需要设置什么才能让完整的类型数据存入集合?
解决方案
直接实例化BsonClassMap时,默认只会映射接口成员,不会自动处理类自身的属性。需要手动调用AutoMap()方法,让驱动扫描并映射类型的所有公共成员(包括类自身定义的属性)。
修改反射注册代码如下:
var types = AppDomain.CurrentDomain.GetAssemblies() .SelectMany(i => i.GetTypes()) .Where(t => typeof(IEventData).IsAssignableFrom(t) && !t.IsInterface && !t.IsAbstract); foreach (var type in types) { if (!BsonClassMap.IsClassMapRegistered(type)) { var classMap = new BsonClassMap(type); // 自动映射当前类型的所有公共成员(接口+类自身属性) classMap.AutoMap(); // 显式设置类型鉴别器,和泛型注册的默认行为对齐 classMap.SetDiscriminator(type.Name); BsonClassMap.RegisterClassMap(classMap); } }
关键说明:
AutoMap()是核心:它会递归扫描类型的所有公共属性、字段,包括继承自接口的成员和类自身定义的成员。- 过滤抽象类:添加
!t.IsAbstract避免注册无法实例化的抽象类型。 - 显式设置鉴别器:
SetDiscriminator(type.Name)确保类型鉴别器和泛型注册的默认逻辑一致,保证反序列化时能正确识别类型。
修改后,非泛型注册的类映射就能像泛型版本一样,将完整的类型数据序列化到MongoDB集合中。
内容的提问来源于stack exchange,提问作者Juzzbott
相关产品推荐
相关产品推荐

