由于传统迁移,我需要使用protobuf-net.dll v2
反序列化由protobuf-net.dll v1
序列化的对象,其中类层次结构是一个简单的3层继承结构。
以下是v1
生成的protogen.exe
带注释的类:
[ProtoContract]
public class DerivedAgainV1
{
[ProtoMember(1, IsRequired = false, Name = @"Name", DataFormat = ProtoBuf.DataFormat.Default)]
[System.ComponentModel.DefaultValue(null)]
public string Name;
[ProtoMember(2, IsRequired = false, Name = @"TimeStamp", DataFormat = ProtoBuf.DataFormat.TwosComplement)]
[System.ComponentModel.DefaultValue(default(long))]
public long TimeStamp;
[ProtoMember(3, IsRequired = false, Name = @"Value", DataFormat = ProtoBuf.DataFormat.TwosComplement)]
[System.ComponentModel.DefaultValue(default(double))]
public double Value;
[ProtoMember(4, IsRequired = false, Name = @"Version", DataFormat = ProtoBuf.DataFormat.TwosComplement)]
[System.ComponentModel.DefaultValue(default(double))]
public int Version;
public DerivedAgainV1() { }
}
以下是3层继承结构的手动编码v2
类:
[ProtoContract]
[ProtoInclude(1000, typeof(DerivedClassV2))]
public class BaseClassV2
{
[ProtoMember(1, IsRequired = false, Name = @"Name", DataFormat = ProtoBuf.DataFormat.Default)]
[System.ComponentModel.DefaultValue(null)]
public string Name;
[ProtoMember(2, IsRequired = false, Name = @"TimeStamp", DataFormat = ProtoBuf.DataFormat.TwosComplement)]
[System.ComponentModel.DefaultValue(default(long))]
private long TimeStampSerializable
{
get {
return DateTimeToTicksSinceEpoch(TimeStamp);
}
set {
TimeStamp = TicksSinceEpochToDateTime(value);
}
}
public DateTime TimeStamp;
public BaseClassV2() {}
private static readonly long originTicks = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified).Ticks;
private long DateTimeToTicksSinceEpoch(DateTime value)
{
return value.Ticks - originTicks;
}
private DateTime TicksSinceEpochToDateTime(long ticks)
{
return new DateTime(originTicks + ticks);
}
}
[ProtoContract]
[ProtoInclude(1000, typeof(DerivedAgainV2))]
public class DerivedClassV2 : BaseClassV2
{
[ProtoMember(1, IsRequired = false, Name = @"Value", DataFormat = ProtoBuf.DataFormat.TwosComplement)]
[System.ComponentModel.DefaultValue(default(double))]
public double Value;
public DerivedClassV2() {}
}
[ProtoContract]
public class DerivedAgainV2 : DerivedClassV2
{
[ProtoMember(1, IsRequired = false, Name = @"Version", DataFormat = ProtoBuf.DataFormat.TwosComplement)]
[System.ComponentModel.DefaultValue(default(int))]
public int Version;
public DerivedAgainV2() {}
}
首先创建DerivedAgainV1
设置所有字段的实例,使用protobuf-net v1
序列化,并将字节写入文件:
var item = new DerivedAgainV1()
{
Name = "DerivedAgain";
TimeStamp = (new DateTime(2000, 1, 1)).Ticks - (new DateTime(1970, 1, 1)).Ticks;
Value = 1.0;
Version = 1;
}
using (var stream = new MemoryStream())
{
Serializer.Serialize(stream, item); // protobuf-net.dll v1
stream.Seek(0, SeekOrigin.Begin);
using (var file = new FileStream(path, FileMode.Create, FileAccess.Write))
{
stream.CopyTo(file);
}
}
然后从文件加载字节,并使用protobuf-net.dll v2
将反序列化的字节合并到DerivedAgainV2
的新实例中:
var bytes = File.ReadAllBytes(path);
using (var stream = new MemoryStream(bytes))
{
var item = Serializer.Merge(stream, new DerivedAgainV2()); // protobuf-net.dll v2
}
不会抛出异常,但那些不属于DerivedAgainV2
成员的BaseClassV2
字段会产生意外值:
item.Name = "DerivedAgain"
item.TimeStamp = {1/1/2000 12:00:00 AM}
item.Value = 0.0
item.Version = 0