如@Marc所说,线路格式只发送项目数据,因此为了知道列表是否为空或null,您必须向流添加该信息。 添加额外的属性以指示原始集合是否为空很容易,但如果您不想修改原始类型定义,则有另外两个选项:
使用代理序列化
代理类型将具有额外的属性(保持原始类型不变),并将恢复列表的原始状态:null,带有项目或为空。
[TestMethod]
public void SerializeEmptyCollectionUsingSurrogate_RemainEmpty()
{
var instance = new SomeType { Items = new List<int>() };
RuntimeTypeModel.Default.Add(typeof(SomeType), true).SetSurrogate(typeof(SomeTypeSurrogate));
var clone = Serializer.DeepClone(instance);
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>() };
var clone = Serializer.DeepClone(instance);
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>();
}
}