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

Сериализация и десериализация объектов, реализующих абстрактные классы с использованием Protobuf-net

Фон

Я пытаюсь заставить приведенный ниже класс сериализовать и десериализовать класс, который реализует абстрактный класс, используя Protobuf-net . Однако при десериализации происходит сбой с ошибкой: «Для AbstractTest не найден конструктор без параметров».

Что я делаю неправильно?

Что я пробовал

Я потратил много времени на поиск ответа, но очень немногие вопросы связаны с абстрактным характером моего вопроса.

Минимальный пример

    public class TestRunner
    {
        public void Go()
        {
            string encoded = Serialize<ConcreteTest>(new ConcreteTest());

            object ob = Deserialize(new System.IO.MemoryStream(Encoding.ASCII.GetBytes(encoded)));
        }

        public static string Serialize<T>(T data)
        {
            MemoryStream outputStream = new MemoryStream();
            Serializer.Serialize<T>(outputStream, data);
            outputStream.Position = 0;

            StreamReader outputReader = new StreamReader(outputStream);
            return outputReader.ReadToEnd();
        }

        public static object Deserialize(Stream data)
        {
             AbstractTest test = Serializer.Deserialize<AbstractTest>(data);
             //Error from the line above: No parameterless constructor found for AbstractTest

            if (test.ID == 3)
            {
                 return Serializer.Deserialize<ConcreteTest>(data);
            }

            throw new Exception("We don't know how to handle the message type if I got here!");
        }
    }


[ProtoBuf.ProtoContract]
[ProtoBuf.ProtoInclude(25, typeof(ConcreteTest))]
public abstract class AbstractTest
{
    public AbstractTest()
    {

    }

    [ProtoBuf.ProtoMember(1)]
    public int ID = 3;

    public abstract void Test();
}


[ProtoBuf.ProtoContract]
public class ConcreteTest : AbstractTest
{
    [ProtoBuf.ProtoMember(2)]
    public int ID2 = 4;
    public override void Test()
    {
         MasterLog.DebugWriteLine("It worked!");
    }
}

  • К вашему сведению, мой ответ здесь предполагает, что вам действительно нужны данные в виде текстовой строки. Однако обратите внимание, что обычно лучше просто избегать использования данных в виде строки, поэтому, если возможно, я бы посоветовал просто не делать этого. Если вы не уверены и хотите обсудить, что вы делаете, чтобы выяснить, можно ли избежать строки, дайте мне знать. 28.04.2018

Ответы:


1

Первоначальная проблема заключается в том, что вы испортили данные, используя Encoding в обратном порядке. Encoding преобразует произвольный текст в отформатированный двоичный файл (что означает: отформатированный в соответствии с правилами этой «кодировки»), а отформатированный двоичный файл обратно в произвольный текст. Он предназначен для описания того, как записывать текст в поток. Вы использовали его в обратном порядке, что означает: вы использовали его для преобразования произвольного двоичного файла в другом формате в строку. Возможно, вы также использовали две разные кодировки (по умолчанию StreamReader почти наверняка не будет использовать ASCII).

Итак: вы не можете использовать здесь Encoding. Что вы можете использовать, так это base-64; Например:

using (var outputStream = new MemoryStream())
{
    Serializer.Serialize<T>(outputStream, data);

    return Convert.ToBase64String(outputStream.GetBuffer(),
        0, (int)outputStream.Length);
}

Вы можете изменить это, используя Convert.FromBase64String:

using (var ms = new System.IO.MemoryStream(Convert.FromBase64String(encoded)))
{
    object ob = Deserialize(ms);
    Console.WriteLine(ob.ToString());
}

Также существует проблема, когда вы дважды десериализуете поток без перемотки, что означает, что вторая десериализация работает с нулевыми байтами, что означает, что он пытается создать экземпляр абстрактного типа; поэтому вам также нужно исправить метод Deserialize:

public static object Deserialize(Stream data)
{
    AbstractTest test = Serializer.Deserialize<AbstractTest>(data);

    return test;
}

При этом все работает корректно.

28.04.2018
  • Спасибо, что напомнили мне о правильной обработке потоков с помощью операторов using в вашем коде! Прошло много времени с тех пор, как я использовал поток. 30.04.2018
  • Новые материалы

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

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

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

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

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

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

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