2015-01-23 14 views
14

Gần đây tôi đã chuyển đến số new MongoDB C# driver v2.0 từ số deprecated v1.9.BsonSerializationException khi tuần tự hóa từ điển <DateTime,T> đến BSON

Bây giờ, khi tôi serialize một lớp học có một cuốn từ điển đôi khi tôi chạy vào BsonSerializationException sau:

MongoDB.Bson.BsonSerializationException: Khi sử dụng DictionaryRepresentation.Document giá trị then chốt phải serialize như dây đàn.

Dưới đây là một sinh sản tối thiểu:

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

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

Trả lời

28

Vấn đề là người lái xe mới serializes điển như một tài liệu theo mặc định.

Các MongoDB C# lái ​​xe có 3 cách để serialize một từ điển: Document, ArrayOfArrays & ArrayOfDocuments (more on that in the docs). Khi nó nối tiếp thành một tài liệu, các khóa từ điển là tên của phần tử BSON có một số hạn chế (ví dụ, như lỗi đề xuất, chúng phải được tuần tự hóa thành chuỗi).

Trong trường hợp này, các phím của từ điển là DateTime s không được phân loại dưới dạng chuỗi, nhưng là Date để chúng tôi cần chọn một số DictionaryRepresentation khác.

Để thay đổi tuần tự của tài sản cụ thể này, chúng ta có thể sử dụng thuộc tính BsonDictionaryOptions với một khác nhau DictionaryRepresentation:

[BsonDictionaryOptions(DictionaryRepresentation.ArrayOfArrays)] 
public Dictionary<DateTime, int> Dictionary { get; private set; } 

Tuy nhiên, chúng ta cần phải làm điều đó trên tất cả các thành viên có vấn đề cá nhân. Để áp dụng điều này DictionaryRepresentation cho tất cả các thành viên có liên quan, chúng tôi có thể thực hiện một ước mới:

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)); 
    } 
} 

Mà chúng ta đăng ký như sau:

ConventionRegistry.Register(
    "DictionaryRepresentationConvention", 
    new ConventionPack {new DictionaryRepresentationConvention(DictionaryRepresentation.ArrayOfArrays)}, 
    _ => true); 
Các vấn đề liên quan