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

#c# #.net #class #protobuf-net

#c# #.net #класс #protobuf-net

Вопрос:

Используя последнюю бета-версию 2.0 для ProtoBuf.net Я пытаюсь сериализовать производный класс (просто пример) и получаю пустой файл. Почему свойства базового класса не сериализуются?

 [ProtoContract]
[Serializable]
public class Web2PdfClient : Web2PdfEntity
{

}

[ProtoContract]
[Serializable]
public class Web2PdfEntity : EngineEntity
{

    [ProtoMember(1)]
    public string Title { get; set; }
    [ProtoMember(2)]
    public string CUrl { get; set; }
    [ProtoMember(3)]
    public string FileName { get; set; }

}


[ProtoContract]
[Serializable]
public class EngineEntity
{

    public bool Result { get; set; }
    public string ErrorMessage { get; set; }
    public bool IsMembershipActive { get; set; }
    public int ConversionTimeout { get; set; }
    public byte[] FileStorage { get; set; }
}
  

При использовании приведенного ниже кода для сериализации класса я получаю пустой файл.

 var Web2PDF = new Web2PdfClient
                          {                                
                              CUrl = "http://www.google.com",
                              FileName = "test.txt"
                          };
        using (var file = File.Create(@"C:UsersAdministratorProjectstemptest.bin"))
        {
            Serializer.Serialize(file, Web2PDF);

        }
  

Ответ №1:

На самом деле, я весьма удивлен, что это не вызвало исключения — я проведу расследование! Для того, чтобы это работало, базовый тип должен иметь уникальный способ обозначения каждого из подтипов. Это может быть указано через атрибуты или (в версии v2) во время выполнения. Например:

 [ProtoContract]
[Serializable]
public class Web2PdfClient : Web2PdfEntity
{

}

[ProtoContract]
[ProtoInclude(7, typeof(Web2PdfClient))]
[Serializable]
public class Web2PdfEntity : EngineEntity
{ ... }
  

В этом нет ничего особенного 7 за исключением того, что он не должен конфликтовать с любыми другими элементами, определенными для этого типа. Может быть определено несколько подтипов (с разными тегами). Обратите также внимание, что protobuf-net не просматривает [Serializable] , поэтому вам это не нужно, если вы также не используете BinaryFormatter (или аналогичный).

Аналогично, EngineEntity следует рекламировать его ожидаемые подтипы и указывать элементы для сериализации (и по какому тегу).

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

1. Марк, у меня есть дополнительный вопрос, надеюсь, можно задать с помощью комментария, потому что это связано с этим вопросом. Вы сказали, что базовый класс должен быть помечен атрибутом, который указывает на унаследованный класс. Что делать, если базовый класс находится в отдельной библиотеке классов? Я не могу поместить [ProtoInclude(7, typeof(MyInheritedClass))] в базовый класс, потому что я получу сообщение об ошибке, что MyInheritedClass не разрешен.

2. @Tomas — если базовый тип не знает о производных типах, то вы также можете настроить его во время выполнения в версии v2, используя TypeModel и AddSubType; т.е. typeModel.Add(typeof(Web2PdfEntity), false).AddSubType(7, typeof(Web2PdfClient)); и использовать typeModel.Serialize и т.д. (кэшировать и повторно использовать модель, поскольку она включает сгенерированный IL и т.д.)