From 55ff1ef5dea84b3a87dd1a6f8623c5a47d50cdb5 Mon Sep 17 00:00:00 2001 From: Travis Parks Date: Wed, 25 Jun 2014 11:04:51 -0400 Subject: [PATCH] Even more powerful dictionary detection There were some more cases where an IDictionary was not being detected by the UpcastDictionary. --- mustache-sharp.test/UpcastDictionaryTester.cs | 17 +++++++ mustache-sharp/Properties/AssemblyInfo.cs | 4 +- mustache-sharp/UpcastDictionary.cs | 46 +++++++++++++++++-- 3 files changed, 60 insertions(+), 7 deletions(-) diff --git a/mustache-sharp.test/UpcastDictionaryTester.cs b/mustache-sharp.test/UpcastDictionaryTester.cs index 7eca0ba..2b8b50d 100644 --- a/mustache-sharp.test/UpcastDictionaryTester.cs +++ b/mustache-sharp.test/UpcastDictionaryTester.cs @@ -202,5 +202,22 @@ namespace Mustache.Test }; CollectionAssert.AreEqual(expected, values, "The enumerator did not return the correct pairs."); } + + /// + /// Newtonsoft's JSON.NET has an object called JObject. This is a concrete class + /// that inherits from IDictionary<string, JToken>. The UpcastDictionary + /// should be able to handle this type. + /// + [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 + { + } } } diff --git a/mustache-sharp/Properties/AssemblyInfo.cs b/mustache-sharp/Properties/AssemblyInfo.cs index d6e4db0..d0e4d00 100644 --- a/mustache-sharp/Properties/AssemblyInfo.cs +++ b/mustache-sharp/Properties/AssemblyInfo.cs @@ -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")] \ No newline at end of file diff --git a/mustache-sharp/UpcastDictionary.cs b/mustache-sharp/UpcastDictionary.cs index a823c6c..9d48ead 100644 --- a/mustache-sharp/UpcastDictionary.cs +++ b/mustache-sharp/UpcastDictionary.cs @@ -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 getTypes(Type type) + { + HashSet types = new HashSet(); + getTypes(types, type); + return types; + } + + private static void getTypes(HashSet 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 getDictionary(IEnumerable types, object source) + { + var dictionaries = from type in types + let valueType = getValueType(type) + where valueType != null + let upcastType = typeof(UpcastDictionary<>).MakeGenericType(valueType) + select (IDictionary)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)Activator.CreateInstance(upcastType, source); + return valueType; } }