2011-11-27 5 views
2

Во время моего переключения из BinaryFormatter в protobuf-net, Я наблюдал разницу при сериализации коллекций.Deserializing Collections with protobuf-net

В примере кода ниже, Deserialize (Protobuf-сеть v2r470) возвращает различные результаты, если массив создается экземпляр в пределах класс (Street1), чем снаружи (street2).

Не разрешено ли сериализовать коллекции, созданные в декларации класса?

[ProtoContract] 
public class City 
{ 
    [ProtoMember(1)] 
    public string[] streets1; 

    [ProtoMember(2)] 
    public string[] streets2 = new string[2]; 
} 

City city = new City(); 

// Instantiate and populate streets1 
city.streets1 = new string[2]; 
city.streets1[0] = "streetA"; 
city.streets1[1] = "streetB"; 

// Populate streets2. Already instantiated 
city.streets2[0] = "streetA"; 
city.streets2[1] = "streetB"; 

// Serializing 
using (var file = File.Create("city.bin")) 
{ 
    Serializer.Serialize(file, city); 
} 

// Deserializing 
using (var file = File.OpenRead("city.bin")) 
{ 
    City getCity = Serializer.Deserialize<City>(file); 
} 

Deserialize загружает следующее getCity:

getCity.streets1: "streetA", "streetB" (как и ожидалось)

getCity.streets2: NULL, NULL, "streetA", " streetB "< --------- Почему нуль?

Есть так много нулевых возвратов, поскольку в коллекции есть элементы.

ответ

3

Это, но проблема в том, что Protobuf-сеть берет на себя (за счет concatenatable природы формата Protobuf), что он должен продлить (добавить в) списки/массивы, и ваше поле-инициализатор начинает его в длина 2.

есть по крайней мере 3 исправлений здесь:

  • вы можете добавить SkipConstructor = True в ProtoContract, что будет означать, что не работает поле инициализатору
  • есть «заменить списков "на ProtoMember, который сообщает ему заменить а не добавлял (я не могу вспомнить фактический вариант, но он есть)
  • вы можете добавить до-десериализации обратный вызов, чтобы очистить поле между конструктором и десериализациями
+1

Спасибо! [ProtoContract (SkipConstructor = true)] работает отлично, а также [ProtoMember (1, OverwriteList = true)] для каждого поля коллекции. Счастливый снова! – StefanS