2012-03-20 4 views
8

私はMongoDBを初めて使用しており、F#クラスのシリアル化を行うためにC#ドライバを入手しようとしています。変更可能なF#フィールド&をパラメータなしのコンストラクタを使用してクラスオートマッパで処理していますが、実際には不変性を保持する必要があるため、カスタム直列化を実行するためにIBsonSerializerを実装し始めました。私はこれらのいずれかを書くためのドキュメントが見つかりませんでしたので、ドライバのソースコードから推測しようとしました。MongoDBカスタムシリアライザの実装

私は、シリアライザでDeserializeメソッドが呼び出されたときに、CurrentBsonTypeが、私が期待しているようにStartではなく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); 
}