Реализация пользовательского сериализатора MongoDB
Я новичок в MongoDB и пытаюсь заставить драйвер C# работать с сериализацией классов F#. Я работаю с классом automapper, используя изменяемые поля F# и конструктор без параметров, но на самом деле мне нужно сохранить неизменность, поэтому я начал искать реализацию IBsonSerializer для выполнения пользовательской сериализации. Я не нашел никакой документации для написания одного из них, поэтому просто попытался сделать вывод из исходного кода драйвера.
я столкнулся с проблемой, в которой когда метод Deserialize вызывается в сериализаторе, CurrentBsonType имеет значение EndOfDocument, а не start, как я ожидаю. Я написал эквивалент на C#, чтобы убедиться, что это не какая-то странность F#, но проблема сохраняется. Часть сериализации, похоже, работает нормально и запрашивается из оболочки. Вот пример кода:
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 в десериализации, когда CurrentBsonType не является документом. Я использую последнюю версию 1.4 источника драйвера.
1 ответов
Я понял это в конце. Я должен был использовать bsonReader.GetCurrentBsonType () вместо bsonReader.CurrentBsonType. Это считывает BsonType из буфера, а не просто смотрит на последнюю вещь там. Я также исправил последующую ошибку derserializing. Обновленный метод выглядит следующим образом:
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);
}