I am in the middle of converting serialization in our huge project from BinarySerializers to ProtoBuf, using protobuf-net library.
I have some classes where members have the type object
, which needs some custom logic to include the type name before being able to deserialize to member again.
This is quite easy if I just use a surrogate - but I am concerned that this would result in unnecessary many allocations.
I would rather just implement a custom Serializer, which seems to be possible through [ProtoContryt(Serializer=typeof(CustomSerializer)]
Is there a documentation on how to implement such a serializer? In particular the property SerializerFeatures
is not very clear to me.
The truth is: this is an advanced API that is not really very external-user-friendly; it is mainly designed for internal usage.
The SerializerFeatures
describes a wide range of flags, but primarily what is needed is a category and a wire-type; the category tells it what we're doing, and the wire-type tells it how we're planning to do it; for most "message" types (meaning: something that can itself have sub-values), you almost certainly want SerializerFeatures.WireTypeString | SerializerFeatures.CategoryMessage
, i.e. "this is a 'message', to be serialized using 'length prefix' semantics by default" (although each call-site can override the wire-type preference if needed).
Some examples can be found in the custom serializer used in protobuf-net.Reflection (which needs to work in cases where ref-emit is not allowed, hence the custom serializer); for example - however, note that most of this code was actually obtained by running the regular protobuf-net ref-emit mechanism to generate a dll, then reverse-engineering the IL from that dll back to C#! I say this as a "if the code looks weird: that's why". I've deliberately linked to a slightly humanized portion of the file, i.e. it uses switch
instead of if
. But even then it retains some weirdness - for example the string local1 = name;
actually comes from a "push, dup, conditional-jump, consume|pop" setup.