Как сказал @Marc, проводной формат отправляет данные только для элементов, поэтому, чтобы узнать, был ли список пустым или нулевым, вы должны добавить этот бит информации в поток.
Добавление дополнительного свойства, чтобы указать, был ли исходный коллекция была пустой или нет, это просто, но если вы не хотите изменять исходное определение типа, у вас есть еще два варианта:
Сериализация с использованием суррогата
Суррогатный тип будет иметь дополнительное свойство (сохраняя исходный тип нетронутым) и восстановит исходное состояние списка: нуль, с элементами или пустой.
[TestMethod]
public void SerializeEmptyCollectionUsingSurrogate_RemainEmpty()
{
var instance = new SomeType { Items = new List<int>() };
// set the surrogate
RuntimeTypeModel.Default.Add(typeof(SomeType), true).SetSurrogate(typeof(SomeTypeSurrogate));
// serialize-deserialize using cloning
var clone = Serializer.DeepClone(instance);
// clone is not null and empty
Assert.IsNotNull(clone.Items);
Assert.AreEqual(0, clone.Items.Count);
}
[ProtoContract]
public class SomeType
{
[ProtoMember(1)]
public List<int> Items { get; set; }
}
[ProtoContract]
public class SomeTypeSurrogate
{
[ProtoMember(1)]
public List<int> Items { get; set; }
[ProtoMember(2)]
public bool ItemsIsEmpty { get; set; }
public static implicit operator SomeTypeSurrogate(SomeType value)
{
return value != null
? new SomeTypeSurrogate { Items = value.Items, ItemsIsEmpty = value.Items != null && value.Items.Count == 0 }
: null;
}
public static implicit operator SomeType(SomeTypeSurrogate value)
{
return value != null
? new SomeType { Items = value.ItemsIsEmpty ? new List<int>() : value.Items }
: null;
}
}
Сделайте ваши типы расширяемыми
protobuf-net предлагает интерфейс IExtensible, который позволяет вам расширять типы, чтобы поля можно было добавлять в сообщение без каких-либо нарушений (подробнее см. здесь). Чтобы использовать расширение protobuf-net, вы можете наследовать класс Extensible
или реализовать интерфейс IExtensible
, чтобы избежать ограничения наследования.
Теперь, когда ваш тип является «расширяемым», вы определяете методы [OnSerializing]
и [OnDeserialized]
для добавления новых индикаторов, которые будут сериализованы. в поток и десериализоваться из него при реконструкции объекта с его исходным состоянием.
Плюсы в том, что вам не нужно определять новые свойства или новые типы в качестве суррогатов, минусы в том, что IExtensible
не поддерживается, если ваш тип иметь подтипы, определенные в вашей модели типов.
[TestMethod]
public void SerializeEmptyCollectionInExtensibleType_RemainEmpty()
{
var instance = new Store { Products = new List<string>() };
// serialize-deserialize using cloning
var clone = Serializer.DeepClone(instance);
// clone is not null and empty
Assert.IsNotNull(clone.Products);
Assert.AreEqual(0, clone.Products.Count);
}
[ProtoContract]
public class Store : Extensible
{
[ProtoMember(1)]
public List<string> Products { get; set; }
[OnSerializing]
public void OnDeserializing()
{
var productsListIsEmpty = this.Products != null && this.Products.Count == 0;
Extensible.AppendValue(this, 101, productsListIsEmpty);
}
[OnDeserialized]
public void OnDeserialized()
{
var productsListIsEmpty = Extensible.GetValue<bool>(this, 101);
if (productsListIsEmpty)
this.Products = new List<string>();
}
}
person
Tamir
schedule
09.07.2015