#c# #protocol-buffers #protobuf-net
#c# #протокол-буферы #protobuf-net
Вопрос:
У меня есть классы, которые имеют все необходимые атрибуты для сериализации, и я сохраняю их в system.object, чтобы, когда другой конец десериализует их, он мог сопоставлять их с шаблоном и выполнять разные действия в зависимости от типа объекта.
object data = MyObject;
Serializer.SerializeWithLengthPrefix(stream, data, PrefixStyle.Fixed32); // exception happens here
Пробовал использовать другие методы сериализации, такие как XML / BinaryFormatter, и, похоже, проблем не возникло.
Комментарии:
1. Попробуйте привести его к вашему типу. Protobuf ожидает тип, который может быть сериализован, и System . Объект не может
2. Нет, мне нужно сопоставить его с шаблоном при десериализации. Вы можете сделать это с помощью BinaryFormatter, поэтому я не уверен, следует ли создавать базовый класс для всех объектов для наследования
3. Система. Объект не имеет необходимых атрибутов для сериализации, отсюда и ваша ошибка.
4. Нужно ли мне создавать фиктивный базовый класс для наследования всех классов ..? кажется выполнимой идеей, но уродливой.
5. Я думаю, что это может быть лучшим способом. Пока этот класс сериализуем с помощью protobuf, вы должны нормально передавать свой объект как этот тип.
Ответ №1:
Исключение здесь очень наглядное — protobuf-net не может сериализовать system.object, поскольку не было сказано, как его сериализовать / десериализовать. Это не ограничение protobuf-net, protobuf (спецификация) — это метод сериализации контракта, поэтому для его сериализации требуется спецификация для типа.
Один из вариантов — создать базовый класс, помеченный атрибутом ProtoContract, и наследовать оттуда. Обязательно включите все подклассы в базовый класс с помощью ProtoInclude-attribute, иначе сериализатор не будет знать, как сериализовать подклассы.
Я бы посоветовал не делать этого, поскольку сериализация подклассов — это своего рода дополнение к protobuf-net, предоставляемое поверх стандартного поведения protobuf, и создает проблемы, если вам нужно работать с другими библиотеками и / или языками. Вместо этого я бы посоветовал вам создать формат обмена сообщениями, в котором вы кодируете тип объекта отдельно (сообщение в терминах protobuf). Например, закодируйте тип как enum как первые 4 байта в начале сообщения, за которым следует сам объект. Тогда вы можете сначала прочитать тип, а затем десериализовать соответствующим образом, не прибегая к подклассам.
Комментарии:
1. Вы имеете в виду что-то вроде: напишите перечисление в поток, который вызывается, например, Person, а затем напишите объект типа Person после? Десериализовать перечисление, проверить тип, а затем десериализовать тип в зависимости от результата перечисления?
2. @Jackou Да, именно так. Это также имеет дополнительный бонус, заключающийся в том, что вы можете пропустить десериализацию типа сообщения, который вас не интересует, для потенциального повышения производительности.