Как сериализовать наследуемый класс с помощью ProtoBuf-Net

Извините, если это дубликат. Я искал в нескольких местах ответ, который мог бы понять, включая:

ProtoBuf.net Свойства базового класса не включены при сериализации производного класса

Сериализация наследуемых классов с использованием protobuf-Net

Мои извинения, но я не очень понял ответы. Я ищу более быстрый и компактный двоичный сериализатор, и ProtoBuf выглядит так, как будто это может быть ответом. Мне нужно сериализовать набор классов, которые все происходят из одного базового класса. Их много, поэтому перед тем, как редактировать код класса, я провел простой тест. Также я не хочу изменять классы каким-либо образом, который может повлиять на десериализацию старых постоянных файлов, созданных с помощью двоичного сериализатора NET.

Это базовый класс:

[ProtoContract]
    public class BaseClass
    {
        [ProtoMember(1)]
        public string Name
        {
            get; set;
        }
        [ProtoMember(2)]
        public int Age
        {
            get; set;
        }
    }

Это производный класс:

[ProtoContract]
    public class SubClass1 : BaseClass
    {
        [ProtoMember(3)]
        public string Town
        {
            get; set;
        }

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

Это код для сериализации и десериализации (взят прямо из Руководства по началу работы).

var person = new SubClass1 { Age = 25, Name = "Fred", Town = "Denbigh", Sex = Sex.Female };

            using (var file = File.Create(filename))
            {
                Serializer.Serialize(file, person);
            }

и десериализовать:

SubClass1 newPerson;
            using (var file = File.OpenRead(filename))
            {
                newPerson = Serializer.Deserialize<SubClass1>(file);
            }

            MessageBox.Show(newPerson.Name + 
                " : " + newPerson.Town + 
                " : " + newPerson.Age.ToString() + 
                " : " + newPerson.Sex);

Результат ": Денби: 0: Женский"

Каким-то образом значения из свойств базового класса не сериализуются? Первоначально я протестировал его с индексами ProtoMember для производного класса как 1, 2. Я думал, что это не сработает, поэтому пошел на 3, 4. Кажется, нет никакой разницы. В своей паранойе я выполнил тот же тест, используя стандартный двоичный сериализатор NET, и получил ожидаемый результат: «Фред: Денби: 25: женщина»

Что мне не хватает, пожалуйста?

Ответы на вопрос(2)

Решение Вопроса

Вам нужно использоватьProtoInclude атрибут вашего базового класса:

[ProtoContract]
[ProtoInclude(500, typeof(SubClass1 ))]
public class BaseClass
{

Идентификатор arg (500 в приведенном выше примере) должен быть уникальным для этого класса. Видетьэто статья для получения дополнительной информации

 ScruffyDuck20 окт. 2012 г., 16:02
Большое спасибо - так просто
 Marc Gravell♦20 окт. 2012 г., 16:15
Спасает меня, набрав, та
 Rush Frisby19 дек. 2014 г., 21:15
Дизайн этого кажется задом наперед. Что если у меня есть базовый класс в другой библиотеке, который не знает (и не должен) знать о классах в моем приложении? Можете ли вы вместо этого добавить номер тега в подкласс?
 RenniePet31 авг. 2013 г., 13:20
Ссылка вроде битая ...
 wal20 дек. 2014 г., 15:00
@rushonerok Я также должен отметить: с v2 protobuf-net вы можете создать сериализатор на лету, что означает, что вам не нужно украшать классы атрибутами <plug>, смотрите мою статьюwallaceturner.com/serialization-with-protobuf-net Я использую этот метод в приложениях для обработки описанного вами случая - то есть я определяю модель сериализации, которая знает (ссылается) на все классы в моем приложении, которые требуют сериализации - это означает, что ваши базовые классы могут оставаться в неведении относительно любых подклассов и до сих пор сериализации!

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

[ProtoContract]
public class SubClass1 : BaseClass
{
    [ProtoMember(1)]
    public string BaseName
    {
        get{return base.Name;}
        set{base.Name = value;}
    }

    ...

    [ProtoMember(3)]
    public string Town
    {
        get; set;
    }

    [ProtoMember(4)]
    public Sex Sex
    {
        get; set;
    }
}
 BaltoStar09 нояб. 2016 г., 01:43
Я не думаю, что это будет работать, потому чтоSubClass1 будет иметь два свойства, определенные какProtoMember с индексом = 1 (Name а такжеBaseName )

Ваш ответ на вопрос