Сериализовать или закодировать элемент proto в байтовый массив

#c# #protobuf-net

#c# #protobuf-net

Вопрос:

У меня есть элементы proto, которые выглядят следующим образом

 String = "1324211127562612736"
Varint = 1
Varint = 10000000000
  

Как я могу сериализовать в байтовый массив, где результат должен выглядеть так?

 0x0a, 0x13, 0x31, 0x33, 0x32, 0x34, 0x32, 0x31, 0x31, 0x31, 0x32, 0x37, 0x35, 0x36, 0x32, 0x36, 0x31, 0x32, 0x37, 0x33, 0x36, 0x20, 0x01, 0x28, 0x80, 0xc8, 0xaf, 0xa0, 0x25
  

Ответ №1:

Запустив шестнадцатеричный 0A133133323432313131323735363236313237333620012880C8AFA025 код через https://protogen.marcgravell.com/decode , мы видим, что у нас есть:

 Field #1: 0A String Length = 19, Hex = 13, UTF8 = "1324211127562612 ..." (total 19 chars)
Field #4: 20 Varint Value = 1, Hex = 01
Field #5: 28 Varint Value = 10000000000, Hex = 80-C8-AF-A0-25
  

который сообщает нам номера полей; итак, давайте попробуем:

 [ProtoContract]
class Foo
{
    [ProtoMember(1)]
    public string X { get; set; }

    [ProtoMember(4)]
    public int Y { get; set; }

    [ProtoMember(5)]
    public long Z { get; set; }
}
  

и мы можем генерировать полезную нагрузку с помощью сериализации:

 var foo = new Foo { X = "1324211127562612736", Y = 1, Z = 10000000000 };
using var ms = new MemoryStream();
Serializer.Serialize(ms, foo);
if (!ms.TryGetBuffer(out var buffer))
{   // in reality we should never hit this - TryGetBuffer should work
    buffer = new ArraySegment<byte>(ms.ToArray());
}
Console.WriteLine(BitConverter.ToString(buffer.Array, buffer.Offset, buffer.Count));
  

который выводит:

 0A-13-31-33-32-34-32-31-31-31-32-37-35-36-32-36-31-32-37-33-36-20-01-28-80-C8-AF-A0-25
  

Комментарии:

1. Ваша поддержка этой библиотеки потрясающая. Кстати, откуда вы знаете ProtoMember , что X = 1, Y = 4 и Z = 5?

2. @derodevil это первый бит, в котором я расшифровал опубликованные вами байты — видите, как он сообщает нам номера полей? затем мне просто нужно было сопоставить, какое поле означало какое значение; здесь это было немного просто, поскольку значения были настолько разными. Если вы имеете в виду имена : я их придумал — я не могу дать вам разумные имена, извините

3. Однако это дает мне grpc: error unmarshalling request: proto: apc_request.InitReq: illegal tag 0 (wire type 0)

4. @derodevi общее предположение: вы отправили .Array из an ArraySegment<byte> , не рассматривая также .Offset и .Count ? Это базовый буфер, который является негабаритным; если вам нужен буфер правильного размера (по какой-либо причине): просто используйте ToArray() — это будет немного дороже, обратите внимание

5. О, моя ошибка. Хорошо, это работает хорошо. Большое вам спасибо. Отличная библиотека!