【问题标题】: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);
}

【问题讨论】:

    标签: protobuf-net


    【解决方案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 引入现有的网络应用程序
    猜你喜欢
    • 1970-01-01
    • 2016-12-17
    • 2020-03-09
    • 2023-03-08
    • 2019-02-16
    • 2015-09-20
    • 1970-01-01
    • 2022-06-14
    • 2011-10-05
    相关资源
    最近更新 更多