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], no
Order`),那么 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 - 流不支持并发 IO 读取或写入操作
使用 protobuf-net,是不是可以在不分配内存的情况下反序列化消息?