2015-11-03 138 views
5

我創建了一個自定義列表類維護一組項目的id性能方面的原因:反序列化的自定義列表

public class MyCustomList : List<ItemWithID> 
{ 
    private HashSet<int> itemIDs = new HashSet<int>(); 

    public MyCustomList() 
    { 
    } 

    [JsonConstructor] 
    public MyCustomList(IEnumerable<ItemWithID> collection) 
     : base(collection) 
    { 
     itemIDs = new HashSet<int>(this.Select(i => i.ID)); 
    } 

    public new void Add(ItemWithID item) 
    { 
     base.Add(item); 
     itemIDs.Add(item.ID); 
    } 

    public new bool Remove(ItemWithID item) 
    { 
     var removed = base.Remove(item); 
     if (removed) 
     { 
      itemIDs.Remove(item.ID); 
     } 
     return removed; 
    } 

    public bool ContainsID(int id) 
    { 
     return itemIDs.Contains(id); 
    } 
} 

我想從一個簡單的JSON陣列例如反序列化名單:

JsonConvert.DeserializeObject<MyCustomList>("[{ID:8},{ID:9}]"); 

這將導致JSON.NET只調用空構造函數,所以我的itemID列表保持爲空。 Add方法也不被調用。

JSON.NET如何將項目添加到列表中,以便我可以在該位置添加邏輯。

(這是關於反序列化,而不應該是在JSON字符串持久性,所以建議重複的問題無關,與此一)

+1

不是重複的(請參閱更新的問題) –

+1

您的問題不是JSON反序列化,如果您希望能夠*重寫*'Add'方法,'MyCustomList'需要從'IList'派生。有關詳細信息,請參見[THIS](http://stackoverflow.com/q/580202/2140173)。 – 2015-11-03 11:41:54

+0

@Meehow現在感謝我瞭解新和覆蓋之間的區別。讓這個答案,我會接受它。 –

回答

0

你的問題不在於反序列化JSON,你MyCustomList類需要從IList推導,如果你希望能夠覆蓋Add方法。詳情請參閱THIS

2

你可以反序列化的構造函數需要的形式,然後調用你自己。

var collection = JsonConvert.DeserializeObject<ItemID[]>("[{ID:8},{ID:9}]"); 

var aCustomList = new MyCustomList(collection); 
+0

請問除了它被分成兩行之外,這與現在的實現有什麼不同嗎? – 2015-11-03 11:36:33

+0

唯一的缺點是當MyCustomList被另一方反序列化時(例如WebAPI),項目ID列表將再次爲空。 –

+1

@Meehow區別在於JsonConvert反序列化的類型。此外,然後使用該結果調用所需的構造函數。在原始代碼中調用空構造函數。 – JonMac1374

3

解決方案:

public class MyCustomList : IList<ItemWithID> 
{ 
    private HashSet<int> itemIDs = new HashSet<int>(); 
    private List<ItemWithID> actualList = new List<ItemWithID>(); 

    public void Add(ItemWithID item) 
    { 
     actualList.Add(item); 
     itemIDs.Add(item.ID); 
    } 

    public bool Remove(ItemWithID item) 
    { 
     var removed = actualList.Remove(item); 
     if (removed) 
     { 
      itemIDs.Remove(item.ID); 
     } 
     return removed; 
    } 

    public bool ContainsID(int id) 
    { 
     return itemIDs.Contains(id); 
    } 

    public int IndexOf(ItemWithID item) 
    { 
     return actualList.IndexOf(item); 
    } 

    public void Insert(int index, ItemWithID item) 
    { 
     actualList.Insert(index, item); 
     itemIDs.Add(item.ID); 
    } 

    public void RemoveAt(int index) 
    { 
     itemIDs.Remove(actualList[index].ID); 
     actualList.RemoveAt(index); 

    } 

    public ItemWithID this[int index] 
    { 
     get 
     { 
      return actualList[index]; 
     } 
     set 
     { 
      actualList[index] = value; 
      if (!itemIDs.Contains(value.ID)) 
      { 
       itemIDs.Add(value.ID); 
      } 
     } 
    } 

    public void Clear() 
    { 
     actualList.Clear(); 
     itemIDs.Clear(); 
    } 

    public bool Contains(ItemWithID item) 
    { 
     return actualList.Contains(item); 
    } 

    public void CopyTo(ItemWithID[] array, int arrayIndex) 
    { 
     actualList.CopyTo(array, arrayIndex); 
    } 

    public int Count 
    { 
     get { return actualList.Count; } 
    } 

    public bool IsReadOnly 
    { 
     get { return false; } 
    } 

    public IEnumerator<ItemWithID> GetEnumerator() 
    { 
     return actualList.GetEnumerator(); 
    } 

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 
    { 
     return GetEnumerator(); 
    } 
}