protobuf-net:v2使用继承

时间:2017-01-18 04:34:29

标签: c# inheritance serialization deserialization protobuf-net

由于传统迁移,我需要使用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

0 个答案:

没有答案