Nano Hash - криптовалюты, майнинг, программирование

Унаследованная сериализация класса protobuf-net

После сериализации унаследованного класса C2 поток выглядит так:

0x5a 0x03

0x08 0x97 0x01

0x08 0x96 0x01

Я не могу понять, что это первая группа байтов (5a 03)? Я полагал, что это должны быть только вторые и третьи, которые представляют значения Z1 и Z2?

Мой код:

    [ProtoContract]
    class C1
    {
        [ProtoMember(1, DataFormat = DataFormat.Default)]
        public int Z1 { get; set; }
    }

    [ProtoContract]
    class C2 : C1
    {
        [ProtoMember(1, DataFormat = DataFormat.Default)]
        public int Z2 { get; set; }
    }      

    public static void Main()
    {
        MemoryStream stream = new MemoryStream();
        ProtoBuf.Meta.RuntimeTypeModel.Default.Add(typeof(C1), true).AddSubType(11, typeof(C2));
        C2 c2 = new C2() {Z1 = 150, Z2 = 151};           
        Serializer.Serialize(stream, c2);
    }
13.12.2012

Ответы:


1
  • 0x5a = номер поля 11, тип проводника 2 (с префиксом длины) — это представляет наследование через инкапсуляцию подклассов в виде внутренних сообщений.
  • 0x03 = 3 (length of payload)
    • 0x08 = field 1, wire-type 0 (varint)
    • 0x97 0x01 = 151 (варинт = обратный порядок байтов с использованием MSB в качестве продолжения)
  • 0x08 = field number 1, wire-type 0 (varint)
    • 0x96 0x01 = 150

который в основном соответствует (в .proto)

message C1 {
    optional int32 Z1 = 1;
    optional C2 c2 = 11;
}
message C2 {
    optional int32 Z2 = 1;
}
13.12.2012
  • Вы писали в другой ветке (если я правильно помню), что наследование не является частью спецификации protobuf. Так почему сериализация выглядит именно так (с инкапсуляцией перед пакетом)? Любой способ устранить это, так что это будет что-то вроде этого: [code]message C1 { optional int32 Z1 = 1; } сообщение C2 { необязательный int32 Z2 = 1; }[/код] 14.12.2012
  • @GromHellscream действительно, наследование не является частью спецификации protobuf; protobuf-net для удобства предлагает реализацию с использованием инкапсуляции. Сериализация не находится перед пакетом — все это представляет собой одно сообщение protobuf, которое можно использовать на любой платформе. То, что вы предлагаете, не имеет смысла: ни одно не включает другое. Вся проблема здесь в том, что, когда речь идет о наследовании, вам нужно иметь возможность отправлять любое, чтобы вы могли отправить просто C1 (а не подкласс C2), или новый подкласс C3 C1 или C2. protobuf-net может справиться с этим. Если ты... 14.12.2012
  • @GromHellscream ... хотите полностью сгладить свою модель (потеря поддержки замены), тогда это тоже можно сделать, но в основном вы получите что-то вроде message C2 { Z1 = 1; Z2 = 2; } - вы можете сделать это довольно легко, но: тогда это не на самом деле не поддерживают наследование в обычном значении этого слова. 14.12.2012
  • В моем случае мне не нужна поддержка подстановки и наследования данных внутри сериализованного пакета, потому что обе стороны (клиент и сервер) имеют описание иерархии всех типов на своих сторонах. На самом деле серверная часть представляет собой встроенное устройство и использует чистый С++ protobuf, который не поддерживает соглашение о наследовании protobuf-net (да, я могу его реализовать, но это будет бесполезно для производительности). Иерархия типов представляет высокоуровневые сущности, зависящие от предметной области, поэтому использование вложенных свойств или классов одноуровневой иерархии очень неудобно. 14.12.2012
  • Почему protobuf-net не может просто собрать все свойства, отмеченные атрибутом ProtoMember, из всех базовых классов, если я не изменил RuntimeTypeModel (или явно определил это поведение)? 14.12.2012
  • @GromHellscream ну, для начала: потому что это дало бы два определения для поля 1 в вашем примере, что явно не работает. Но также: чаще модели наследования предназначены для отражения наследования в сериализации, чтобы его можно было реконструировать. Это не относится к вашему случаю. Как это бывает, модель типов можно настроить так, как вы хотите, во время выполнения, но, честно говоря, я бы предложил более уместно смоделировать ее как DTO, которая представляет то, как вы хотите, чтобы она выглядела, то есть без наследования. 14.12.2012
  • @MarcGrovell, конечно, идентификаторы полей должны быть уникальными во всей иерархии типов, это не проблема. 14.12.2012
  • Я понимаю ваше видение модели наследования. Но было бы неплохо иметь и простую форму сериализации. Думаю многим будет полезно. И спасибо за предложение, я рассмотрю его. 14.12.2012
  • почему после операции Serializer.NonGeneric.Deserialize(typeof(C2), stream), где C2 из OP, кроме строки с ProtoBuf.Meta.RuntimeTypeModel, позиция потока становится 6, хотя десериализовано всего 3 байта? 14.12.2012
  • @Grom, почему вы думаете, что он десериализовал только 3 байта? Также: вы имеете в виду 8 (не 6)? 14.12.2012
  • я десериализовал этот поток: {0x10, 0x97, 0x01, 0x08, 0x96, 0x01} и обнаружил, что protobuf-net считывает 6 байтов вместо 3 (что, как я полагаю, должно быть). Вот мой тест: pastebin.com/QiSaAmBS 14.12.2012
  • @Grom ах, верно - я думал, вы все еще имеете в виду данные из ОП (поскольку вы упомянули ОП). Как вы думаете, почему он должен читать только 3 байта? Сериализованные данные - все 6. 14.12.2012
  • Потому что он игнорирует все параметры базового класса (которые не принадлежат RuntimeTypeModel) при сериализации (поэтому в моем примере это будет 3 байта). Также во время десериализации он считывает 6 байтов, но пропускает первые 3, поэтому они теряются навсегда. Также я полагаю, что десериализация должна быть обратной операцией для сериализации, которая не работает в вашем случае. 14.12.2012
  • @Grom, не видя, точно как вы настроили RuntimeTypeModel, невозможно много сказать. Но поток protobuf всегда читается до конца, если вы не закрепите длину. У вас есть полный пример вашего кода, чтобы я мог прокомментировать? 14.12.2012
  • Я вообще не настраивал RuntimeTypeModel, потому что не хочу сериализовать само наследование (только данные из всех базовых классов). Я уже публиковал эту ссылку выше pastebin.com/QiSaAmBS . Здесь нельзя пропустить код. 14.12.2012
  • @Grom Гром, хм, более уверен, что я видел комментарий 14-го числа; Надо будет поискать, но сегодня занят с семьей 24.12.2012
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..