2012-03-20 4 views
8

MongoDB를 처음 사용하고 있으며 C# 드라이버가 F # 클래스를 serialize하는 작업을 수행하려고합니다. 나는 변수 자동 생성자와 함께 가변성 F # 필드를 사용하여 & 매개 변수없는 생성자를 사용하지만 진정으로 불변성을 유지해야하므로 사용자 지정 직렬화를 수행하기 위해 IBsonSerializer를 구현하는 방법을 살펴보기 시작했습니다. 나는이 중 하나를 작성하기위한 문서를 찾지 못했기 때문에 드라이버 소스 코드에서 추측하려고 시도했다.MongoDB 사용자 지정 serializer 구현

Deserialize 메서드가 serializer에서 호출 될 때 CurrentBsonType이 내가 기대하는 것보다 EndOfDocument로 설정되는 문제가 발생했습니다. 나는 C#에서 동등한 내용을 썼다. # F # 별난 아니었지만 문제는 계속된다. 직렬화 부분은 제대로 작동하는 것으로 보이며 셸에서 쿼리 할 수 ​​있습니다. CurrentBsonType이 문서화되어 있지 않은 경우

class Calendar { 
    public string Id { get; private set; } 
    public DateTime[] Holidays { get; private set; } 

    public Calendar(string id, DateTime[] holidays) { 
     Id = id; 
     Holidays = holidays; 
    } 
} 

class CalendarSerializer : BsonBaseSerializer { 
    public override void Serialize(BsonWriter bsonWriter, Type nominalType, object value, IBsonSerializationOptions options) { 
     var calendar = (Calendar) value; 
     bsonWriter.WriteStartDocument(); 
     bsonWriter.WriteString("_id", calendar.Id); 
     bsonWriter.WriteName("holidays"); 
     var ser = new ArraySerializer<DateTime>(); 
     ser.Serialize(bsonWriter, typeof(DateTime[]), calendar.Holidays, null); 
     bsonWriter.WriteEndDocument(); 
    } 

    public override object Deserialize(BsonReader bsonReader, Type nominalType, Type actualType, IBsonSerializationOptions options) { 
     if (nominalType != typeof(Calendar) || actualType != typeof(Calendar)) 
      throw new BsonSerializationException(); 

     if (bsonReader.CurrentBsonType != BsonType.Document) 
      throw new FileFormatException(); 

     bsonReader.ReadStartDocument(); 
     var id = bsonReader.ReadString("_id"); 
     var ser = new ArraySerializer<DateTime>(); 
     var holidays = (DateTime[])ser.Deserialize(bsonReader, typeof(DateTime[]), null); 
     bsonReader.ReadEndDocument(); 
     return new Calendar(id, holidays); 
    } 

    public override bool GetDocumentId(object document, out object id, out Type idNominalType, out IIdGenerator idGenerator) { 
     var calendar = (Calendar) document; 
     id = calendar.Id; 
     idNominalType = typeof (string); 
     idGenerator = new StringObjectIdGenerator(); 
     return true; 
    } 

    public override void SetDocumentId(object document, object id) { 
     throw new NotImplementedException("SetDocumentId is not implemented"); 
    } 
} 

이 역 직렬화에 FileFormatException와 불면 : 다음 샘플 코드입니다. 드라이버 소스의 최신 버전 1.4를 사용하고 있습니다.

답변

7

나는 이것을 결국 알아 냈다. bsonReader.CurrentBsonType 대신 bsonReader.GetCurrentBsonType()을 사용해야합니다. 이것은 BsonType을 버퍼에서 읽어 오지 않고 마지막 위치에서 읽습니다. 나는 또한 후속 버그 디시리얼라이징을 수정했다. 업데이트 된 방법은 다음과 같습니다.

public override object Deserialize(BsonReader bsonReader, Type nominalType, Type actualType, IBsonSerializationOptions options) { 
    if (nominalType != typeof(Calendar) || actualType != typeof(Calendar)) 
     throw new BsonSerializationException(); 

    if (bsonReader.GetCurrentBsonType() != BsonType.Document) 
     throw new FileFormatException(); 

    bsonReader.ReadStartDocument(); 
    var id = bsonReader.ReadString("_id"); 
    bsonReader.ReadName(); 
    var ser = new ArraySerializer<DateTime>(); 
    var holidays = (DateTime[])ser.Deserialize(bsonReader, typeof(DateTime[]), null); 
    bsonReader.ReadEndDocument(); 
    return new Calendar(id, holidays); 
} 
관련 문제