Như @Marc nói, định dạng dây chỉ gửi dữ liệu cho các mục, do đó, để biết danh sách có trống hay không, bạn phải thêm thông tin đó vào luồng.
Thêm bất động sản thêm để cho biết bộ sưu tập ban đầu là rỗng hoặc không phải là dễ dàng, nhưng nếu bạn không muốn thay đổi định nghĩa kiểu ban đầu bạn có thêm hai lựa chọn:
Serialize Sử dụng Surrogate
Các loại thay thế sẽ có thuộc tính bổ sung (giữ nguyên kiểu gốc của bạn) và sẽ khôi phục trạng thái ban đầu của danh sách: null, với các mục hoặc rỗng.
[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;
}
}
Hãy loại của bạn Extensible
protobuf-net cho thấy giao diện IExtensible cho phép bạn mở rộng các loại để các lĩnh vực có thể được thêm vào một thông điệp mà không cần bất cứ điều gì phá vỡ (đọc thêm here) . Để sử dụng phần mở rộng protobuf-net, bạn có thể kế thừa lớp Extensible
hoặc triển khai giao diện IExtensible
để tránh ràng buộc thừa kế.
Bây giờ loại của bạn là "có thể mở rộng", bạn xác định các phương pháp [OnSerializing]
và [OnDeserialized]
để thêm các chỉ số mới sẽ được tuần tự hóa vào luồng và được khử tuần tự từ khi tạo lại đối tượng với trạng thái ban đầu.
Ưu điểm là bạn không cần phải xác định thuộc tính mới cũng như loại mới là người thay thế, khuyết điểm là IExtensible
không được hỗ trợ nếu loại của bạn có loại phụ được xác định trong kiểu mô hình của bạn.
[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>();
}
}