Modified:
/src/Jayrock.Json/Json/Conversion/Converters/DictionaryImporter.cs
/src/Jayrock.Json/Json/Conversion/ImportContext.cs
/src/Jayrock.Json/Reflection/Reflector.cs
/tests/Jayrock/Json/Conversion/TestImportContext.cs
=======================================
--- /src/Jayrock.Json/Json/Conversion/Converters/DictionaryImporter.cs Fri
Apr 15 16:09:54 2011
+++ /src/Jayrock.Json/Json/Conversion/Converters/DictionaryImporter.cs Tue
Apr 19 17:35:06 2011
@@ -48,7 +48,10 @@
public class DictionaryImporter<TKey, TValue> : ImporterBase
{
public DictionaryImporter() :
- base(typeof(IDictionary<TKey, TValue>)) { }
+ this(typeof(IDictionary<TKey, TValue>)) { }
+
+ protected DictionaryImporter(Type outputType) :
+ base(outputType) { }
protected override object ImportFromObject(ImportContext context,
JsonReader reader)
{
@@ -84,7 +87,7 @@
return ReadReturning(reader, dictionary);
}
- protected virtual Dictionary<TKey, TValue> CreateDictionary()
+ protected virtual IDictionary<TKey, TValue> CreateDictionary()
{
IEqualityComparer<TKey> comparer = IsKeyOfString
? (IEqualityComparer<TKey>) StringComparer.Ordinal
@@ -98,6 +101,19 @@
get { return Type.GetTypeCode(typeof(TKey)) ==
TypeCode.String; }
}
}
+
+ internal sealed class DictionaryImporter<TDictionary, TKey, TValue> :
+ DictionaryImporter<TKey, TValue>
+ where TDictionary : IDictionary<TKey, TValue>, new()
+ {
+ public DictionaryImporter() :
+ base(typeof(TDictionary)) {}
+
+ protected override IDictionary<TKey, TValue> CreateDictionary()
+ {
+ return new TDictionary();
+ }
+ }
#endif // !NET_1_0 && !NET_1_1
}
=======================================
--- /src/Jayrock.Json/Json/Conversion/ImportContext.cs Fri Apr 15 16:09:54
2011
+++ /src/Jayrock.Json/Json/Conversion/ImportContext.cs Tue Apr 19 17:35:06
2011
@@ -28,7 +28,6 @@
using System.Collections;
using System.Configuration;
using System.Diagnostics;
- using System.Threading;
using Jayrock.Json.Conversion.Converters;
using Jayrock.Reflection;
#if !NET_1_0 && !NET_1_1
@@ -153,7 +152,18 @@
if (Reflector.IsConstructionOfGenericTypeDefinition(type,
typeof(IDictionary<,>)))
return (IImporter)
Activator.CreateInstance(typeof(DictionaryImporter<,>).MakeGenericType(type.GetGenericArguments()));
- #endif
+ Type genericDictionaryType =
Reflector.FindConstructionOfGenericInterfaceDefinition(type,
typeof(IDictionary<,>));
+ if (genericDictionaryType != null)
+ {
+ var args2 = genericDictionaryType.GetGenericArguments();
+ Debug.Assert(args2.Length == 2);
+ Type[] args3 = new Type[3];
+ args3[0] = type; // [ TDictionary, ... , ... ]
+ args2.CopyTo(args3, 1); // [ TDictionary, TKey, TValue ]
+ return
(IImporter)Activator.CreateInstance(typeof(DictionaryImporter<,,>).MakeGenericType(args3));
+ }
+
+ #endif // !NET_1_0 && !NET_1_1
#if !NET_1_0 && !NET_1_1 && !NET_2_0
=======================================
--- /src/Jayrock.Json/Reflection/Reflector.cs Fri Apr 15 16:09:54 2011
+++ /src/Jayrock.Json/Reflection/Reflector.cs Tue Apr 19 17:35:06 2011
@@ -25,6 +25,7 @@
#region Imports
using System;
+ using System.Reflection;
#endregion
@@ -75,6 +76,30 @@
&& !type.IsGenericTypeDefinition
&& type.GetGenericTypeDefinition() ==
genericTypeDefinition;
}
+
+ /// <summary>
+ /// Finds and returns the constructed type of an interface
+ /// generic type definition if the type implements it. Otherwise
+ /// returns a <c>null</c> reference.
+ /// </summary>
+ /// <exception cref="System.ArgumentNullException">
+ /// Either <paramref name="type"/> or <paramref
name="genericTypeDefinition"/>
+ /// is a null reference.
+ /// </exception>
+
+ internal static Type
FindConstructionOfGenericInterfaceDefinition(Type type, Type
genericTypeDefinition)
+ {
+ if (type == null) throw new ArgumentNullException("type");
+ if (genericTypeDefinition == null) throw new
ArgumentNullException("genericTypeDefinition");
+
+ Type[] interfaces = type.FindInterfaces(new
TypeFilter(IsConstructionOfGenericInterfaceDefinition),
genericTypeDefinition);
+ return interfaces.Length == 0 ? null : interfaces[0];
+ }
+
+ private static bool
IsConstructionOfGenericInterfaceDefinition(Type type, object criteria)
+ {
+ return IsConstructionOfGenericTypeDefinition(type, (Type)
criteria);
+ }
#endif // !NET_1_0 && !NET_1_1
=======================================
--- /tests/Jayrock/Json/Conversion/TestImportContext.cs Fri Apr 15 16:09:54
2011
+++ /tests/Jayrock/Json/Conversion/TestImportContext.cs Tue Apr 19 17:35:06
2011
@@ -69,6 +69,7 @@
AssertInStock(typeof(NullableImporter), typeof(int?));
AssertInStock(typeof(DictionaryImporter<string, string>),
typeof(System.Collections.Generic.IDictionary<string, string>));
AssertInStock(typeof(DictionaryImporter<int, object>),
typeof(System.Collections.Generic.IDictionary<int, object>));
+ AssertInStock(typeof(DictionaryImporter<Guid, string>),
typeof(SubDictionaryThing));
// TODO Use AssertInStock once CollectionImporter is public
Assert.IsNotNull(new
ImportContext().FindImporter(typeof(System.Collections.Generic.IList<string>)));
@@ -159,5 +160,109 @@
public int Field1;
public int Field2;
}
+
+ #if !NET_1_0 && !NET_1_1
+
+ internal class DictionaryThing :
System.Collections.Generic.IDictionary<Guid, string>
+ {
+ #region Implementation of IEnumerable
+
+ public
System.Collections.Generic.IEnumerator<System.Collections.Generic.KeyValuePair<Guid,
string>> GetEnumerator()
+ {
+ throw new NotImplementedException();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+
+ #endregion
+
+ #region Implementation of
ICollection<KeyValuePair<Guid,string>>
+
+ public void Add(System.Collections.Generic.KeyValuePair<Guid,
string> item)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Clear()
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool
Contains(System.Collections.Generic.KeyValuePair<Guid, string> item)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void
CopyTo(System.Collections.Generic.KeyValuePair<Guid, string>[] array, int
arrayIndex)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool
Remove(System.Collections.Generic.KeyValuePair<Guid, string> item)
+ {
+ throw new NotImplementedException();
+ }
+
+ public int Count
+ {
+ get { throw new NotImplementedException(); }
+ }
+
+ public bool IsReadOnly
+ {
+ get { throw new NotImplementedException(); }
+ }
+
+ #endregion
+
+ #region Implementation of IDictionary<Guid,string>
+
+ public bool ContainsKey(Guid key)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Add(Guid key, string value)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool Remove(Guid key)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool TryGetValue(Guid key, out string value)
+ {
+ throw new NotImplementedException();
+ }
+
+ public string this[Guid key]
+ {
+ get { throw new NotImplementedException(); }
+ set { throw new NotImplementedException(); }
+ }
+
+ public System.Collections.Generic.ICollection<Guid> Keys
+ {
+ get { throw new NotImplementedException(); }
+ }
+
+ public System.Collections.Generic.ICollection<string> Values
+ {
+ get { throw new NotImplementedException(); }
+ }
+
+ #endregion
+ }
+
+ private sealed class SubDictionaryThing : DictionaryThing
+ {
+ }
+
+ #endif // !NET_1_0 && !NET_1_1
}
}