I translate my project to use protobuf-net instead of BinaryFormatter. It looks like there is a lack of documentation http://code.google.com/p/protobuf-net/w/list I also looked up some examples from http://code.google.com/p/protobuf-net/source/browse/ But some things is still not clear for me and that's why i decide to ask here:
1. About ISerializable and Serializer.Merge/Serialize
If we have inheritance from ISerializable to make specific serialization. As i read from: ProtoBuf-Net ProtoInclude Generic Type Subclass we have to use a hook Serializer.Merge/Serialize;
Suppose we have class:
[Serializable]
[ProtoContract]
public class Anchor : ISerializable
{
[ProtoMember(1)]
public int id;
[ProtoMember(2)]
public Ship ship;
...
}
the Serializer.Merge(info, this); must be added to constructor Anchor(SerializationInfo info, StreamingContext context)
and Serializer.Serialize(info, this); added to void GetObjectData(SerializationInfo info, StreamingContext context)
So, we have:
protected Anchor(SerializationInfo info, StreamingContext context)
{
//for binaryformatter:
Type myType = typeof(Anchor);
foreach (SerializationEntry e in info)
{
FieldInfo f = myType.GetField(e.Name,BindingFlags.NonPublic|BindingFlags.Public|BindingFlags.Public|BindingFlags.Instance);
f.SetValue(this,e.Value);
}
//added for protobuf-net:
Serializer.Merge(info, this);
}
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
//for binaryformatter:
foreach (FieldInfo f in typeof(Anchor).GetFields(BindingFlags.NonPublic|BindingFlags.Public|BindingFlags.Instance))
{
if ((f.Attributes&FieldAttributes.NotSerialized)==0)
info.AddValue(f.Name,f.GetValue(this));
}
//added for protobuf-net:
Serializer.Serialize(info, this);
}
Questions: Is this correct? (an "info" is overwrited by Serializer? i.e. binaryformatter will not work properly? at the present point in time i just try to use protobuf-net and l would prefer to leave binaryformatter works properly also)
2. About usage ProtoInclude and RuntimeTypeModel.Default
Suppose we have class Message that is base for classes: class Ack, class HandshakeClientInfo...class Command . If we want to serialize Message's children, as i read from: protobuf-net's [ProtoInclude(1, "MyClass")] did not work we should use a ProtoInclude ("to tell" base class: class Message about it's childrens) in case if we know about children types at compile time - it's ok.
For those childrens which type we cannot determine at compile time (because it is in another project) we should use RuntimeTypeModel.Default[typeof(Message)].AddSubType(207, typeof(Command)); or to use Type.AssemblyQualifiedName: [ProtoInclude(207, "Trainer.Commands.Command, Simulator, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")]
[Serializable]
[ProtoContract]
[ProtoInclude(200, typeof(Ack))]
[ProtoInclude(201, typeof(HandshakeClientInfo))]
[ProtoInclude(202, typeof(HandshakeReadyToSimulation))]
[ProtoInclude(203, typeof(FileMessage))]
[ProtoInclude(204, typeof(HandshakeResponse))]
[ProtoInclude(205, typeof(Sync))]
[ProtoInclude(206, typeof(HandshakeSimulationStart))]
public abstract class Message {
[ProtoMember(1)]
public byte Sender;
...
}
i use protobuf-net v2 (r580) and the variant with RuntimeTypeModel.Default[typeof(Message)].AddSubType(207, typeof(Command)); seems is more preferable.
Questions: But i don't understand where it should be placed in code? in constructor or.... ? And is it allowable to use ProtoInclude and RuntimeTypeModel.Default together?