fhu*_*usb 9 f# mongodb-.net-driver
我是MongoDB的新手,我正在尝试让C#驱动程序工作序列化F#类.我使用可变F#字段和无参数构造函数使用类自动化程序,但实际上我需要保留不变性,所以我开始考虑实现IBsonSerializer来执行自定义序列化.我没有找到任何关于编写其中一个的文档,所以我们只是试图从驱动程序源代码中推断出来.
我遇到了一个问题,当在序列化程序上调用Deserialize方法时,CurrentBsonType被设置为EndOfDocument而不是我期待的开始.我在C#中编写了等效文件,以确保它不是一些F#怪异,但问题仍然存在.序列化部分似乎工作正常,可以从shell查询.以下是示例代码:
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");
}
}
Run Code Online (Sandbox Code Playgroud)
当CurrentBsonType不是Document时,在Deserialize中会出现FileFormatException.我使用的是驱动程序源的最新版本1.4.
我最终想到了这一点.我应该使用bsonReader.GetCurrentBsonType()而不是bsonReader.CurrentBsonType.这会从缓冲区中读取BsonType,而不是只看那里的最后一件事.我还修复了随后的bug 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);
}
Run Code Online (Sandbox Code Playgroud)