Btw, just in case anyone needs to use protobuf with document storage, here it is (although in F#). I haven't tested extensively, but it should correctly save and load tags in the document:
let tagToType = Dictionary<int, Type>()
tagToType.[1] <- typeof<int>
tagToType.[2] <- typeof<int64>
tagToType.[3] <- typeof<double>
tagToType.[4] <- typeof<single>
tagToType.[5] <- typeof<DateTime>
tagToType.[6] <- typeof<string>
tagToType.[7] <- typeof<bool>
let typeToTag = System.Linq.Enumerable.ToDictionary<KeyValuePair<int, Type>, Type, int>(tagToType, (fun kv -> kv.Value), (fun kv -> kv.Key))
let serializeDocument (stream: Stream) (doc: Document) =
let model = RuntimeTypeModel.Default
model.SerializeWithLengthPrefix(stream, doc.Content, typeof<byte []>, PrefixStyle.Base128, 0)
model.SerializeWithLengthPrefix(stream, doc.Key, typeof<string>, PrefixStyle.Base128, 0)
model.SerializeWithLengthPrefix(stream, (if not (isNull doc.Version) then doc.Version else ""), typeof<string>, PrefixStyle.Base128, 0)
if isNull doc.Tags then
model.SerializeWithLengthPrefix(stream, 0, typeof<int>, PrefixStyle.Base128, 0)
else
let elementsCount = doc.Tags.Count
model.SerializeWithLengthPrefix(stream, elementsCount, typeof<int>, PrefixStyle.Base128, 0)
for kv in doc.Tags do
model.SerializeWithLengthPrefix(stream, kv.Key, typeof<int>, PrefixStyle.Base128, 0)
let valueType = kv.Value.GetType()
model.SerializeWithLengthPrefix(stream, kv.Value, valueType, PrefixStyle.Base128, typeToTag.[valueType])
let deserializeDocument (stream: Stream) : Document =
let model = RuntimeTypeModel.Default
let doc = Document()
doc.Content <- model.DeserializeWithLengthPrefix(stream, null, typeof<byte []>, PrefixStyle.Base128, 0) :?> byte[]
doc.Key <- model.DeserializeWithLengthPrefix(stream, null, typeof<string>, PrefixStyle.Base128, 0) :?> string
let version = model.DeserializeWithLengthPrefix(stream, null, typeof<string>, PrefixStyle.Base128, 0) :?> string
if not (String.IsNullOrEmpty version) then doc.Version <- version
let elementsCount = model.DeserializeWithLengthPrefix(stream, null, typeof<int>, PrefixStyle.Base128, 0) :?> int
if elementsCount > 0 then
let tags = Dictionary<string, obj>(elementsCount)
for i = 1 to elementsCount do
let tag = model.DeserializeWithLengthPrefix(stream, null, typeof<string>, PrefixStyle.Base128, 0) :?> string
let value = model.DeserializeWithLengthPrefix(stream, null, null, PrefixStyle.Base128, 0, (fun t -> tagToType.[t]))
tags.[tag] <- value
doc.Tags <- tags
doc
type ProtoSerializer() =
interface IDocumentSerializer with
member x.Deserialize(objType, objectBytes) =
use memStream = new MemoryStream(objectBytes)
if objType = typeof<Document> then
deserializeDocument memStream :> obj
else
Serializer.Deserialize(objType, memStream)
member x.Serialize(obj) =
use memStream = new MemoryStream()
match obj with
| :? Document as doc -> serializeDocument memStream doc
| _ -> Serializer.Serialize(memStream, obj)
memStream.Flush()
memStream.ToArray()