Even more powerful dictionary detection

There were some more cases where an IDictionary<string, T> was not being
detected by the UpcastDictionary.
This commit is contained in:
Travis Parks 2014-06-25 11:04:51 -04:00
parent 80824c4e4b
commit 55ff1ef5de
3 changed files with 60 additions and 7 deletions

View File

@ -202,5 +202,22 @@ namespace Mustache.Test
};
CollectionAssert.AreEqual(expected, values, "The enumerator did not return the correct pairs.");
}
/// <summary>
/// Newtonsoft's JSON.NET has an object called JObject. This is a concrete class
/// that inherits from IDictionary&lt;string, JToken&gt;. The UpcastDictionary
/// should be able to handle this type.
/// </summary>
[TestMethod]
public void ShouldHandleConcreteClassInheritingFromDictionary()
{
var dictionary = new ConcreteDictionary() { { "Name", "Bob" } };
var result = UpcastDictionary.Create(dictionary);
Assert.AreEqual(dictionary["Name"], result["Name"]);
}
public class ConcreteDictionary : Dictionary<string, string>
{
}
}
}

View File

@ -14,6 +14,6 @@ using System.Runtime.InteropServices;
[assembly: CLSCompliant(true)]
[assembly: ComVisible(false)]
[assembly: Guid("e5a4263d-d450-4d85-a4d5-44c0a2822668")]
[assembly: AssemblyVersion("0.2.5.0")]
[assembly: AssemblyFileVersion("0.2.5.0")]
[assembly: AssemblyVersion("0.2.6.0")]
[assembly: AssemblyFileVersion("0.2.6.0")]
[assembly: InternalsVisibleTo("mustache-sharp.test")]

View File

@ -20,11 +20,48 @@ namespace Mustache
return sourceDictionary;
}
Type sourceType = source.GetType();
if (!sourceType.IsGenericType)
var types = getTypes(sourceType);
return getDictionary(types, source);
}
private static IEnumerable<Type> getTypes(Type type)
{
HashSet<Type> types = new HashSet<Type>();
getTypes(types, type);
return types;
}
private static void getTypes(HashSet<Type> types, Type type)
{
if (type == null)
{
return;
}
types.Add(type);
getTypes(types, type.BaseType);
foreach (Type interfaceType in type.GetInterfaces())
{
getTypes(types, interfaceType);
}
}
private static IDictionary<string, object> getDictionary(IEnumerable<Type> types, object source)
{
var dictionaries = from type in types
let valueType = getValueType(type)
where valueType != null
let upcastType = typeof(UpcastDictionary<>).MakeGenericType(valueType)
select (IDictionary<string, object>)Activator.CreateInstance(upcastType, source);
return dictionaries.FirstOrDefault();
}
private static Type getValueType(Type type)
{
if (!type.IsGenericType)
{
return null;
}
Type[] argumentTypes = sourceType.GetGenericArguments();
Type[] argumentTypes = type.GetGenericArguments();
if (argumentTypes.Length != 2)
{
return null;
@ -36,12 +73,11 @@ namespace Mustache
}
Type valueType = argumentTypes[1];
Type genericType = typeof(IDictionary<,>).MakeGenericType(typeof(string), valueType);
if (!genericType.IsAssignableFrom(sourceType))
if (!genericType.IsAssignableFrom(type))
{
return null;
}
Type upcastType = typeof(UpcastDictionary<>).MakeGenericType(valueType);
return (IDictionary<string, object>)Activator.CreateInstance(upcastType, source);
return valueType;
}
}