protobuf-net v2 是不是需要 DataMember(Order=n) 注释?

Posted

技术标签:

【中文标题】protobuf-net v2 是不是需要 DataMember(Order=n) 注释?【英文标题】:Is DataMember(Order=n) annotation required for protobuf-net v2?protobuf-net v2 是否需要 DataMember(Order=n) 注释? 【发布时间】:2011-11-17 22:04:41 【问题描述】:

简单实验:我从 Northwind 创建了一个实体模型,发现如果不添加 Order 属性,生成的类不适用于 protobuf-net v2。有没有办法让实体代码生成器添加Order,或者有没有办法让protobuf-net在没有Order的情况下工作?

我必须改变

[DataMemberAttribute()]

[DataMemberAttribute(Order=1)]

NorthwindEntities e = new NorthwindEntities();

using(var file = File.Create("customers.bin"))

    Serializer.Serialize(file, e.Customers);

【问题讨论】:

【参考方案1】:

需要的是它有办法将成员解析为数字键。这可以采用内联属性的形式——例如,它允许[DataContract]/[DataMember(Order=key)][XmlType]/[XmlElement(Order=key)][ProtoContract]/[ProtoMember(key)]

还可以通过[DataContract] 选择按字母顺序推断合约,但这只有在您的合约类型将来不会改变时才是安全的;为此,请添加:

[ProtoContract(InferTagFromName = true)]

到类型(可能是部分,见下文)。这直接适用于您呈现的场景,其中[DataMember] 表示成员,但没有定义Order。为了稳定性,我个人更喜欢显式布局。

另一个选项甚至不需要像[DataMember] 这样的提示;您可以要求它应用BinaryFormatter 规则(所有字段,公共或私有)或XmlSerializer 规则(公共成员、属性或字段);但是,如果您的类型发生变化,这将非常不稳定!

[ProtoContract(ImplicitFields = ImplicitFields.AllPublic)]

但是;另一个常见的情况是你有来自生成器的类型,你不能方便地编辑,因为任何编辑都会在重新生成时丢失;对于那个场景,partial 类可能会有所帮助。您不能通过属性向成员添加属性,但[ProtoPartialMember] 可以在这里提供帮助。例如,在单独的代码文件中:

[ProtoContract]
[ProtoPartialMember(key, memberName)]
[ProtoPartialMember(anotherKey, anotherMemberName)]
...
public partial class Order 

有时,您无权访问该类型whatsoever,因此添加任何类型的属性都不是一种选择。如果您的场景如您所描述的那样 ([DataContract/[DataMember], noOrder`),那么 lazy 选项是全局启用此功能:

Serializer.GlobalOptions.InferTagFromName = true;

或在 v2 中:

RuntimeTypeModel.Default.InferTagFromNameDefault = true;

对于更复杂的场景,v2 有一个新的 MetaType 模型专门用于此,您可以在运行时配置布局:

RuntimeTypeModel.Default.Add(typeof(Order), false)
            .Add(key, memberName).Add(anotherKey, anotherMemberName);

或者如果你的键是 1, 2, 3, ... 那么只需:

   RuntimeTypeModel.Default.Add(typeof(Order), false)
            .Add(memberName, anotherMemberName, ...);

MetaType 上有无数的选项来控制序列化的各个方面)

认为涵盖了这里的大部分选项!

【讨论】:

RuntimeTypeModel.Default.InferTagFromNameDefault = true;似乎工作谢谢。 @Paul 请注意上面的重点;如果添加成员,那是不稳定,因为它是按字母顺序排列的。如果你加AardvarkCount,一切都会突然变差【参考方案2】:

我才刚刚开始深入研究 ProtoBuf,因此还没有真正查看以前的版本,但我一直在使用查看生成的流,它按预期排序。

<protocontract()>
Public Class Peer
   <ProtoMember(1)>
    Public Property PacketNumber As Long
    <ProtoMember(2)>
    Public Property DateCreated As DateTime
    <ProtoMember(3)>
    Public Property Data As String 
    <ProtoMember(4)>
    Public Property OriginatingTerminal As Integer
end class

希望对你有帮助

【讨论】:

目前是人手,因为我正在将 Protobuf 引入现有的网络应用程序

以上是关于protobuf-net v2 是不是需要 DataMember(Order=n) 注释?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 protobuf-net 中启用字符串实习?

Protobuf-net - 流不支持并发 IO 读取或写入操作

使用 protobuf-net,是不是可以在不分配内存的情况下反序列化消息?

将 protobuf-net RuntimeTypeModel 编译为 C#,而不是 DLL

protobuf-net 是不是支持命名元组?

Protobuf-net 是不是有计划包括验证?