我将我的项目翻译为使用 protobuf-net 而不是 BinaryFormatter。看起来缺少文档http://code.google.com/p/protobuf-net/w/list我还从http://code.google.com/p/protobuf-net 查找了一些示例/source/browse/ 但是有些事情对我来说仍然不清楚,这就是我决定在这里问的原因:
1.关于ISerializable和Serializer.Merge/Serialize
如果我们从 ISerializable 继承来进行特定的序列化。正如我从:ProtoBuf-Net ProtoInclude Generic Type Subclass中读到的, 我们必须使用钩子 Serializer.Merge/Serialize;
假设我们有类:
[Serializable]
[ProtoContract]
public class Anchor : ISerializable
{
[ProtoMember(1)]
public int id;
[ProtoMember(2)]
public Ship ship;
...
}
Serializer.Merge(info, this) ; 必须添加到构造函数Anchor(SerializationInfo info, StreamingContext context)
和 Serializer.Serialize(info, this); 添加到void GetObjectData(SerializationInfo info, StreamingContext context)
所以,我们有:
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);
}
问题: 这是正确的吗?(“信息”被序列化程序覆盖?即 binaryformatter 将无法正常工作?目前我只是尝试使用 protobuf-net,我更愿意让 binaryformatter 也能正常工作)
2.关于使用ProtoInclude和RuntimeTypeModel.Default
假设我们有作为类基础的 Message类:Ack 类、HandshakeClientInfo 类... Command 类。如果我们想序列化 Message 的子类,正如我所读到的那样:protobuf-net 的 [ProtoInclude(1, "MyClass")] 不起作用 ,我们应该使用 ProtoInclude (“告诉”基类:关于它的子类的消息类)以防万一如果我们在编译时知道子类型 - 没关系。
对于那些我们在编译时无法确定的类型(因为它在另一个项目中),我们应该使用RuntimeTypeModel.Default[typeof(Message)].AddSubType(207, typeof(Command)); 或使用 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;
...
}
我使用 protobuf-net v2 (r580) 和带有RuntimeTypeModel.Default[typeof(Message)].AddSubType(207, typeof(Command)) 的变体;似乎更可取。
问题: 但我不明白它应该放在代码中的什么位置?在构造函数或....?可以同时使用ProtoInclude和RuntimeTypeModel.Default吗?