Cod*_*ero 34 protocol-buffers protobuf-net
协议缓冲区如何处理类型版本控制?
例如,当我需要随时间更改类型定义时?喜欢添加和删除字段.
Mar*_*ell 24
谷歌设计的protobuf对版本化非常宽容:
然而:
一般来说,虽然 - 它只会工作,你不需要担心版本控制.
我知道这是一个老问题,但是最近我遇到了这个问题。我解决这个问题的方法是使用Facades和运行时决策进行序列化。这样,我可以将旧的字段和新的消息优雅地处理,以将其弃用/升级为新的字段。
我正在使用Marc Gravell的protobuf.net(v2.3.5)和C#,但是外观理论适用于任何语言和Google的原始protobuf实现。
我的旧班级有一个DateTime时间戳记,我想对其进行更改以包括“ Kind”(。NET过时)。有效地添加它意味着它序列化为9个字节而不是8个字节,这将是一个重大的序列化更改!
[ProtoMember(3, Name = "Timestamp")]
public DateTime Timestamp { get; set; }
Run Code Online (Sandbox Code Playgroud)
protobuf的基本原理是永远不要更改protoid。我想阅读旧的序列化二进制文件,这意味着“ 3”将保留下来。
所以,
我重命名了旧属性并将其设为私有(是的,它仍然可以通过反射魔术来反序列化),但是我的API不再显示它可用!
[ProtoMember(3, Name = "Timestamp-v1")]
private DateTime __Timestamp_v1 = DateTime.MinValue;
Run Code Online (Sandbox Code Playgroud)
我使用新的原型ID创建了一个新的Timestamp属性,并包含了DateTime.Kind
[ProtoMember(30002, Name = "Timestamp", DataFormat = ProtoBuf.DataFormat.WellKnown)]
public DateTime Timestamp { get; set; }
Run Code Online (Sandbox Code Playgroud)
对于旧邮件,我添加了“ AfterDeserialization”方法来更新新时间
[ProtoAfterDeserialization]
private void AfterDeserialization()
{
//V2 Timestamp includes a "kind" - we will stop using __Timestamp - so keep it up to date
if (__Timestamp_v1 != DateTime.MinValue)
{
//Assume the timestamp was in UTC - as it was...
Timestamp = new DateTime(__Timestamp_v1.Ticks, DateTimeKind.Utc) //This is for old messages - we'll update our V2 timestamp...
}
}
Run Code Online (Sandbox Code Playgroud)
现在,我可以正确地对旧消息和新消息进行序列化/反序列化,并且我的时间戳现在包含DateTime.Kind!没坏。
但是,这确实意味着两个字段都将出现在所有新消息中。因此,最后的选择是使用运行时序列化决策来排除旧的时间戳(请注意,如果它使用了protobuf的required属性,它将无法正常工作!!!)
bool ShouldSerialize__Timestamp_v1()
{
return __Timestamp_v1 != DateTime.MinValue;
}
Run Code Online (Sandbox Code Playgroud)
就是这样。我有一个不错的单元测试,如果有人想要的话,可以从头到尾进行...
我知道我的方法依赖于.NET魔术,但是我认为该概念可以翻译成其他语言。
| 归档时间: |
|
| 查看次数: |
20226 次 |
| 最近记录: |