将Dictionary 序列化为BSON时的BsonSerializationException

我最近从已弃用的v1.9转移到了新的MongoDB C#驱动程序v2.0 。

现在,当我序列化一个有字典的类时,我有时遇到以下BsonSerializationException

MongoDB.Bson.BsonSerializationException:使用DictionaryRepresentation.Document时,键值必须序列化为字符串。

这是一个最小的重现:

 class Hamster { public ObjectId Id { get; private set; } public Dictionary Dictionary { get; private set; } public Hamster() { Id = ObjectId.GenerateNewId(); Dictionary = new Dictionary(); Dictionary[DateTime.UtcNow] = 0; } } 

 static void Main() { Console.WriteLine(new Hamster().ToJson()); } 

问题是新驱动程序默认将字典序列化为文档。

MongoDB C#驱动程序有三种方法来序列化字典: DocumentArrayOfArraysArrayOfDocuments ( 更多关于文档中的内容 )。 当它作为文档序列化时,字典键是具有一些限制的BSON元素的名称(例如,如错误所示,它们必须被序列化为字符串)。

在这种情况下,字典的键是DateTime ,它们没有被序列化为字符串,但是作为Date所以我们需要选择另一个DictionaryRepresentation

要更改此特定属性的序列化,我们可以将BsonDictionaryOptions属性与不同的DictionaryRepresentation

 [BsonDictionaryOptions(DictionaryRepresentation.ArrayOfArrays)] public Dictionary Dictionary { get; private set; } 

但是,我们需要分别对每个有问题的成员这样做。 要将此DictionaryRepresentation应用于所有相关成员,我们可以实现一个新约定:

 class DictionaryRepresentationConvention : ConventionBase, IMemberMapConvention { private readonly DictionaryRepresentation _dictionaryRepresentation; public DictionaryRepresentationConvention(DictionaryRepresentation dictionaryRepresentation) { _dictionaryRepresentation = dictionaryRepresentation; } public void Apply(BsonMemberMap memberMap) { memberMap.SetSerializer(ConfigureSerializer(memberMap.GetSerializer())); } private IBsonSerializer ConfigureSerializer(IBsonSerializer serializer) { var dictionaryRepresentationConfigurable = serializer as IDictionaryRepresentationConfigurable; if (dictionaryRepresentationConfigurable != null) { serializer = dictionaryRepresentationConfigurable.WithDictionaryRepresentation(_dictionaryRepresentation); } var childSerializerConfigurable = serializer as IChildSerializerConfigurable; return childSerializerConfigurable == null ? serializer : childSerializerConfigurable.WithChildSerializer(ConfigureSerializer(childSerializerConfigurable.ChildSerializer)); } } 

我们注册如下:

 ConventionRegistry.Register( "DictionaryRepresentationConvention", new ConventionPack {new DictionaryRepresentationConvention(DictionaryRepresentation.ArrayOfArrays)}, _ => true);