BinaryFormatter の代わりに protobuf-net を使用するようにプロジェクトを変換します。ドキュメントが不足しているようです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(情報、 これ); コンストラクター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);
}
質問: これは正しいですか? (「情報」はシリアライザーによって上書きされますか?つまり、バイナリフォーマッターは正しく機能しませんか?現時点では、protobuf-netを使用しようとしていますが、バイナリフォーマッターも適切に動作するようにしたいと思います)
2. ProtoInclude と RuntimeTypeModel.Default の使い方について
クラスのベースとなるクラス Messageがあるとします:クラス Ack、クラス HandshakeClientInfo... クラス Command。私が読んだように、メッセージの子をシリアライズしたい場合: protobuf - net の [ProtoInclude(1, "MyClass")] は機能しませんでした 。コンパイル時に子の型についてわかっていれば、問題ありません。
(別のプロジェクトにあるため) コンパイル時に判別できない型の子には、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を一緒に使用することはできますか?