2016-03-26 6 views
0

Ich habe eine OrderedDictionary mit int Schlüssel und System.Drawing.Rectangle Werte. JSON.NET wird die OrderedDictionary nicht serialisieren ... es gibt ein leeres Objekt zurück. Ich schrieb einen benutzerdefinierten Konverter, aber ich fragte mich, ob es einen einfacheren Weg gab. Zu denken, dass JSON.NET könnte das Vorhandensein eines typisierten enumerator als Auslöser verwenden, um seinen integrierten Code zu verwenden für die Serialisierung und Deserialisierung ein Dictionary<TKey, TValue> ich das versucht:Verwenden von JSON.NET mit OrderedDictionary

class Program 
{ 
    static void Main(string[] args) 
    { 
     var test = new OrderedDictionary<int, Rectangle>(); 
     test.Add(1, new Rectangle(0, 0, 50, 50)); 
     test.Add(42, new Rectangle(1, 1, 1, 1)); 

     string s = JsonConvert.SerializeObject(test); 
     var deserialized = JsonConvert.DeserializeObject<OrderedDictionary<int, Rectangle>>(s); 

     var someRect = deserialized[(object)1]; // someRect is null 
     var someOtherRect = (Rectangle)deserialized["1"]; // InvalidCastException 
    } 
} 

public class OrderedDictionary<TKey, TValue> : OrderedDictionary, IEnumerable<KeyValuePair<TKey, TValue>> 
{ 
    IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator() 
    { 
     foreach (TKey key in Keys) 
     { 
      yield return new KeyValuePair<TKey, TValue>(key, (TValue)this[key]); 
     } 
    } 
} 

Serialisierung perfekt funktioniert. Wenn ich deserialize, werden die Schlüssel in dem Wörterbuch jedoch Zeichenfolgen und die Rectangle s sind JObject s, die nicht in Rectangle umgewandelt werden können. Kann ich meiner Klasse OrderedDictionary<> etwas hinzufügen, das eine korrekte Deserialisierung mit JSON.NET ermöglicht? Vielen Dank.

+0

Welche OrderedDictionary ?, eine in 'System.Collections.Specialized'? – Eser

+0

Ja. Da ich 15 Zeichen verwenden muss, werde ich auch erwähnen, dass ich [diesen Beitrag] (http://stackoverflow.com/questions/2629027/no-generic-implementation-of-ordereddictionary) gelesen habe und über eine der feinen Implementierungen nachdenke dort, aber fürchten das gleiche Deserialisierungsverhalten. –

+0

Es ist möglich, dass JSON.NET noch keine Unterstützung dafür bietet. Sie können diese Anfrage auf https://github.com/JamesNK/Newtonsoft.Json –

Antwort

2

Ihr Problem ist, dass, obwohl Sie einen Enumerator hinzugefügt haben, Dinge wie der Indexer nicht überschrieben werden können. Was Sie also erhalten, ist die Standardimplementierung des nicht-generischen OrderedDictionary, die Ihnen kein typisiertes Ergebnis liefert.

Anstatt also zu erben, benötigen Sie eine Fassade, die die generische Schnittstelle vollständig implementiert.

Sie müssen meine Klasse verifizieren (ich habe gerade den Test gemacht). Ich habe auch mit den Keys und Values-Eigenschaften (sie werden nicht oft verwendet) und einigen der anderen ICollection-Methoden betrogen. Nur faul :)

  [TestMethod] 
    public void TestJson() 
    { 
     var test = new OrderedDictionary<int, Rectangle>(); 
     test.Add(1, new Rectangle(0, 0, 50, 50)); 
     test.Add(42, new Rectangle(1, 1, 1, 1)); 
     string s = JsonConvert.SerializeObject(test); 

     var deserialized = JsonConvert.DeserializeObject<OrderedDictionary<int, Rectangle>>(s); 

     object someRect = deserialized[1]; 
     Assert.IsNotNull(someRect); 
     Assert.IsTrue(someRect is Rectangle); 
    } 

    public class OrderedDictionary<TKey, TValue> : IDictionary<TKey, TValue> 
    { 
     private readonly OrderedDictionary dic = new OrderedDictionary(); 

     public TValue this[TKey key] { get { return default(TValue); } set { } } 

     public void Add(KeyValuePair<TKey, TValue> item) 
     { 
      dic.Add(item.Key, item.Value); 
     } 
     public void Add(TKey key, TValue value) 
     { 
      dic.Add(key, value); 
     } 

     public void Clear() { dic.Clear(); } 


     public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) { } 


     public int Count { get { return dic.Count; } } 
     public bool IsReadOnly { get { return false; } } 

     public bool Contains(TKey key) { return dic.Contains(key); } 
     public bool ContainsKey(TKey key) { return dic.Contains(key); } 

     public bool Remove(TKey key) { dic.Remove(key); return true; } 

     public bool TryGetValue(TKey key, out TValue value) { value = default(TValue); return false; } 

     bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item) 
     { 
      throw new NotImplementedException(); 
     } 
     bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item) { return false; } 

     public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() 
     { 
      foreach (DictionaryEntry entry in dic) 
       yield return new KeyValuePair<TKey, TValue>((TKey)entry.Key, (TValue)entry.Value); 
     } 

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

     private static readonly TKey[] keys = new TKey[0]; 
     private static readonly TValue[] values = new TValue[0]; 

     ICollection<TKey> IDictionary<TKey, TValue>.Keys { get { return keys; } } 
     ICollection<TValue> IDictionary<TKey, TValue>.Values { get { return values; } } 
    } 
+0

Leider hat 'SortedDictionary' nicht das gewünschte Verhalten. Es sortiert Schlüssel ... Ich möchte die Reihenfolge der Einfügung und des Entfernens beibehalten. –

+0

Ich habe die Antwort aktualisiert – AndyPook