using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable;
+using System.Collections.Specialized;
using System.Reflection;
using System.Text.Encodings.Web;
using Xunit;
private class MyClass : IClass { }
+ private class MyNonGenericDictionary : Dictionary<string, int> { }
+
private class MyFactory : JsonConverterFactory
{
public override bool CanConvert(Type typeToConvert)
}
}
+ // This method generates 316 unique test cases for nested dictionaries up to 4
+ // levels deep, along with matching JSON, encompassing the various planes of
+ // dictionaries that can be combined: generic, non-generic, BCL, user-derived,
+ // immutable, mutable, readonly, concurrent, specialized.
private static IEnumerable<(Type, string)> NestedDictionaryTypeData()
{
string testJson = @"{""Key"":1}";
List<Type> genericDictTypes = new List<Type>()
{
typeof(IDictionary<,>),
- typeof(Dictionary<,>),
typeof(ConcurrentDictionary<,>),
+ typeof(GenericIDictionaryWrapper<,>),
};
List<Type> nonGenericDictTypes = new List<Type>()
{
- typeof(IDictionary),
typeof(Hashtable),
+ typeof(OrderedDictionary),
};
List<Type> baseDictionaryTypes = new List<Type>
{
+ typeof(MyNonGenericDictionary),
typeof(IReadOnlyDictionary<string, MyClass>),
- typeof(Dictionary<string, IClass>),
typeof(ConcurrentDictionary<string, int>),
- typeof(ImmutableDictionary<string, object>),
+ typeof(ImmutableDictionary<string, IClass>),
+ typeof(GenericIDictionaryWrapper<string, int?>),
};
baseDictionaryTypes.AddRange(nonGenericDictTypes);
}
}
+ public class GenericIDictionaryWrapper<TKey, TValue> : IDictionary<TKey, TValue>
+ {
+ private Dictionary<TKey, TValue> _dict = new Dictionary<TKey, TValue>();
+
+ public TValue this[TKey key] { get => ((IDictionary<TKey, TValue>)_dict)[key]; set => ((IDictionary<TKey, TValue>)_dict)[key] = value; }
+
+ public ICollection<TKey> Keys => ((IDictionary<TKey, TValue>)_dict).Keys;
+
+ public ICollection<TValue> Values => ((IDictionary<TKey, TValue>)_dict).Values;
+
+ public int Count => ((IDictionary<TKey, TValue>)_dict).Count;
+
+ public bool IsReadOnly => ((IDictionary<TKey, TValue>)_dict).IsReadOnly;
+
+ public void Add(TKey key, TValue value)
+ {
+ ((IDictionary<TKey, TValue>)_dict).Add(key, value);
+ }
+
+ public void Add(KeyValuePair<TKey, TValue> item)
+ {
+ ((IDictionary<TKey, TValue>)_dict).Add(item);
+ }
+
+ public void Clear()
+ {
+ ((IDictionary<TKey, TValue>)_dict).Clear();
+ }
+
+ public bool Contains(KeyValuePair<TKey, TValue> item)
+ {
+ return ((IDictionary<TKey, TValue>)_dict).Contains(item);
+ }
+
+ public bool ContainsKey(TKey key)
+ {
+ return ((IDictionary<TKey, TValue>)_dict).ContainsKey(key);
+ }
+
+ public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
+ {
+ ((IDictionary<TKey, TValue>)_dict).CopyTo(array, arrayIndex);
+ }
+
+ public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
+ {
+ return ((IDictionary<TKey, TValue>)_dict).GetEnumerator();
+ }
+
+ public bool Remove(TKey key)
+ {
+ return ((IDictionary<TKey, TValue>)_dict).Remove(key);
+ }
+
+ public bool Remove(KeyValuePair<TKey, TValue> item)
+ {
+ return ((IDictionary<TKey, TValue>)_dict).Remove(item);
+ }
+
+ public bool TryGetValue(TKey key, out TValue value)
+ {
+ return ((IDictionary<TKey, TValue>)_dict).TryGetValue(key, out value);
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return ((IDictionary<TKey, TValue>)_dict).GetEnumerator();
+ }
+ }
+
public class ReadOnlyStringToStringIDictionaryWrapper : StringToStringIDictionaryWrapper
{
public override bool IsReadOnly => true;