2015-11-03 9 views
5

Ich habe eine benutzerdefinierte List-Klasse, die eine Reihe von Element-IDs aus Performance-Gründen unterhält:Deserialize, um benutzerdefinierte Liste

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); 
    } 
} 

ich diese Liste von einem einfach JSON-Array zB deserialisieren möchten:

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

Dadurch ruft JSON.NET nur den leeren Konstruktor auf, sodass meine itemIDs-Liste leer bleibt. Auch die Add-Methode wird nicht aufgerufen.

Wie fügt JSON.NET die Elemente zur Liste hinzu, damit ich an dieser Stelle Logik hinzufügen kann.

(dies ist etwa Deserialisierung ohne Eigenschaften, die im JSON-String hartnäckig sein sollten, so dass die vorgeschlagene doppelte Frage hat nichts mit diesem zu tun)

+1

kein Duplikat (siehe aktualisierte Frage) –

+1

Ihr Problem besteht nicht in der JSON-Deserialisierung, Ihre 'MyCustomList' muss von' IList' abgeleitet werden, wenn Sie * die 'Add'-Methode überschreiben wollen. Details finden Sie in [THIS] (http://StackOverflow.com/q/580202/2140173). –

+0

@Meowhow danke ich verstehe jetzt den Unterschied zwischen Neu und Override. Mach das zur Antwort und ich werde es akzeptieren. –

Antwort

0

Ihr Problem ist nicht mit JSON Deserialisierung Ihre MyCustomList Klasse muss von IList abzuleiten, ob Sie die Add Methode außer Kraft setzen können, wollen. Details finden Sie unter THIS.

2

Sie dem Konstruktor erwartet in das Formular deserialisieren könnte, dann rufen, dass dich selber.

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

var aCustomList = new MyCustomList(collection); 
+0

Darf ich fragen, wie dies jeder aus der aktuellen Implementierung neben der Tatsache unterscheidet, dass es in zwei Linien aufgeteilt wird? –

+0

Der einzige Nachteil ist, wenn die MyCustomList von einer anderen Partei deserialisiert wird (zB WebAPI), die Item-ID-Liste wieder leer ist. –

+1

@Meehow der Unterschied ist der Typ, von dem JsonConvert deserialisiert. Zusätzlich wird dann der gewünschte Konstruktor mit dem Ergebnis aufgerufen. Im ursprünglichen Code wird der leere Konstruktor aufgerufen. – JonMac1374

3

Lösung:

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(); 
    } 
} 
Verwandte Themen