关于在 Protobuf-net 中实现 VARIANT

问题描述

我有一些 protobuf 解码器字符串,我像这样从 https://protogen.marcgravell.com/decode 解码:

Field #1: 08 Varint Value = 0,Hex = 00
Field #2: 12 String Length = 0,Hex = 00,UTF8 = ""
Field #3: 1A String Length = 51,Hex = 33,UTF8 = "..................." (total 46 chars)
    As sub-object :
    Field #1: 08 Varint Value = 1610099957
Field #4: 20 Varint Value = 2,Hex = 02
Field #5: 2A String Length = 166,Hex = A6-01,UTF8 = "..........................." (total 156 chars)
    As sub-object :
    Field #1: 08 Varint Value = 1610070445
    Field #2: F5 String Length = 148,Hex = D9-E0,UTF8 = "........................." (total 138 chars)
        As sub-object :
        Field #1: 08 String Length = 39,UTF8 = "......" (total 37 chars)
            As sub-object :
            Field #1: 08 Varint Value = 12345678
            Field #2: 33 Varint Value = 3333333333,Hex = 08-F5-D9-E0-FF
Field #6: F5 Varint Value = 1,Hex = D9
Field #7: 42 String Length = 0,UTF8 = ""

如何在 C# 中定义原型类和 varint 大小,如下所示:

[ProtoContract]
public class AllFields
{
    [ProtoMember(1)]
    public int Field1 { get; set; }
    [ProtoMember(2)]
    public string Field2 { get; set; }  
    [ProtoMember(3)]
    public string Field3 { get; set; }   
    public abstract class subField3
    {
        [ProtoMember(1)]
        public long subField3_1 { get; set; }
    }   
    [ProtoMember(4)]
    public int Field4 { get; set; } 
    [ProtoMember(5)]
    public string Field5 { get; set; }  
    public abstract class subField5
    {
    }
    ....
}

以及如何继承子对象

解决方法

varint 的大小由值决定:无需配置或决定。

至于子对象:不要使用 string,而是使用具体(非抽象)类,你应该没问题 - 只需使用该类型而不是 string。该库显示了两种可能性,因为没有模式,它无法确定它是哪一种,因为字符串和子对象使用相同的协议布局。但字段 5 可能是:

[Proto member(5)]
public Whatever SomeName { get; set;}

...

[ProtoContract]
public class Whatever {
    [ProtoMember(1)]
    public int Id {get; set;}

    [ProtoMember(2)]
    public AnotherType AnotherThing {get; set;}
}
,

这是解码字符串:

parser pic

有多个字段 2。

,

我终于明白了:

[ProtoContract]
public class MessageStructs
{
    [ProtoMember(1)]
    public FontsInfo fontInfo;
    [ProtoMember(2)]
    public Structs MsgContent;
}

[ProtoContract]
[ProtoInclude(21,typeof(Structs))]
public interface IInterface
{
    MainContent MessageContent {get;}
    MsgType MessageType {get;}
    Informations MessageOther {get;}
}

[ProtoContract]
public class Structs : IInterface
{
    [ProtoMember(1)]
    public MainContent Message_Content {get; set;}
    [ProtoMember(9)]
    public MsgType Message_Type {get; set;}
    [ProtoMember(37)]
    public Informations Message_Other {get; set;}
}


,

[更新] 我有一些 protobuf 字节数组: 0A27080010F5D9E0FF0518B8C192F00E20002809300038860140024A0CE58D8EE69687E7BB86E9BB9112150A130A11616667647361666473666473667361646612044A0208001215AA02129A010FC80100F00100F80100900200CA0400

现在我定义原型结构如下:

[ProtoContract]
public class MessageStruct
{
    [ProtoMember(1)]
    public FontsInfo fontInfo;
    [ProtoMember(2)]
    public List<MsgContentBase> MsgContent;
}

[ProtoContract]
public class FontsInfo
{
    [ProtoMember(1)]
    public long Field1;
    [ProtoMember(2)]
    public long timestamp;
    [ProtoMember(3)]
    public long Field3;
    [ProtoMember(4)]
    public long Field4;
    [ProtoMember(5)]
    public long fontsize;
    [ProtoMember(6)]
    public long Field6;
    [ProtoMember(7)]
    public long color;
    [ProtoMember(8)]
    public long bold;
    [ProtoMember(9)]
    public string font;
}

[ProtoContract]
[ProtoInclude(20,typeof(MsgType))]
[ProtoInclude(21,typeof(OtherInfo))]
public class MsgContentBase
{
    [ProtoMember(1)]
    public MainContent Main_Content;
    [ProtoMember(2)]
    public MsgType MessageType;
    [ProtoMember(3)]
    public OtherInfo MessageOther;
}
[ProtoContract]
public class MainContent
{
    [ProtoMember(1)]
    public string content;
}
[ProtoContract]
public class MsgType
{
    [ProtoMember(1)]
    public int types;
}
[ProtoContract]
public class OtherInfo
{
    [ProtoMember(37)]
    public Informations info {get; set;}
}
[ProtoContract]
public class Informations
{
    [ProtoMember(25)]
    public int Field1;
    [ProtoMember(30)]
    public int Field2;
    [ProtoMember(31)]
    public int Field3;
    [ProtoMember(34)]
    public int Field4;
    [ProtoMember(73)]
    public string Field5;
}

但我无法得到正确的结果

        Using (MemoryStream mStream = New MemoryStream(New byte[] {0xA,0x27,0x8,0x0,0x10,0xF5,0xD9,0xE0,0xFF,0x5,0x18,0xB8,0xC1,0x92,0xF0,0xE,0x20,0x28,0x9,0x30,0x38,0x86,0x1,0x40,0x2,0x4A,0xC,0xE5,0x8D,0x8E,0xE6,0x96,0x87,0xE7,0xBB,0xE9,0x91,0x12,0x15,0xA,0x13,0x11,0x61,0x66,0x67,0x64,0x73,0x4,0xAA,0x9A,0xF,0xC8,0xF8,0x90,0xCA,0x0}))
    {
       var result = Serializer.Deserialize < MessageStruct > (mStream);
       Console.WriteLine(result.MsgContent(1).MessageType.types);
    }