diff --git a/Local.testsettings b/Local.testsettings
deleted file mode 100644
index 6522637..0000000
--- a/Local.testsettings
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
- These are default test settings for a local test run.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/TraceAndTestImpact.testsettings b/TraceAndTestImpact.testsettings
deleted file mode 100644
index 99dbff3..0000000
--- a/TraceAndTestImpact.testsettings
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
- These are test settings for Trace and Test Impact.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/mustache-sharp.sln b/mustache-sharp.sln
index b2c58b0..9a026f2 100644
--- a/mustache-sharp.sln
+++ b/mustache-sharp.sln
@@ -1,17 +1,10 @@
-Microsoft Visual Studio Solution File, Format Version 11.00
-# Visual Studio 2010
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mustache-sharp", "mustache-sharp\mustache-sharp.csproj", "{D71B378F-A4BA-4263-A4F0-07A49A0C528D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mustache-sharp.test", "mustache-sharp.test\mustache-sharp.test.csproj", "{7F607362-0680-4751-B1DC-621219294AE3}"
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{25414E49-67E6-4B8D-8AD8-78C70F8992A7}"
- ProjectSection(SolutionItems) = preProject
- Local.testsettings = Local.testsettings
- mustache-sharp.vsmdi = mustache-sharp.vsmdi
- TraceAndTestImpact.testsettings = TraceAndTestImpact.testsettings
- EndProjectSection
-EndProject
Global
GlobalSection(TestCaseManagementSettings) = postSolution
CategoryFile = mustache-sharp.vsmdi
diff --git a/mustache-sharp.test/FormatCompilerTester.cs b/mustache-sharp.test/FormatCompilerTester.cs
index dabab3c..c789e85 100644
--- a/mustache-sharp.test/FormatCompilerTester.cs
+++ b/mustache-sharp.test/FormatCompilerTester.cs
@@ -471,6 +471,63 @@ Content";
public string Field;
}
+ ///
+ /// If a derived class replaces a property/field in the base class (via new)
+ /// it should be used, instead of causing an exception or using the base's
+ /// property/field.
+ ///
+ [TestMethod]
+ public void TestGenerate_NewPropertyInDerivedClass_UsesDerivedProperty()
+ {
+ FormatCompiler compiler = new FormatCompiler();
+ const string format = @"Hello, {{Value}}!!!";
+ Generator generator = compiler.Compile(format);
+ DerivedClass instance = new DerivedClass() { Value = "Derived" };
+ string result = generator.Render(instance);
+ Assert.AreEqual("Hello, Derived!!!", result, "The wrong text was generated.");
+ }
+
+ public class BaseClass
+ {
+ public int Value { get; set; }
+ }
+
+ public class DerivedClass : BaseClass
+ {
+ public DerivedClass()
+ {
+ base.Value = 1;
+ }
+
+ public new string Value { get; set; }
+ }
+
+ ///
+ /// If a derived class replaces a property/field in the base class (via new)
+ /// it should be used, instead of causing an exception or using the base's
+ /// property/field.
+ ///
+ [TestMethod]
+ public void TestGenerate_NewPropertyInGenericDerivedClass_UsesDerivedProperty()
+ {
+ FormatCompiler compiler = new FormatCompiler();
+ const string format = @"Hello, {{Value}}!!!";
+ Generator generator = compiler.Compile(format);
+ DerivedClass instance = new DerivedClass() { Value = "Derived" };
+ string result = generator.Render(instance);
+ Assert.AreEqual("Hello, Derived!!!", result, "The wrong text was generated.");
+ }
+
+ public class DerivedClass : BaseClass
+ {
+ public DerivedClass()
+ {
+ base.Value = 1;
+ }
+
+ public new T Value { get; set; }
+ }
+
#endregion
#region Comment
diff --git a/mustache-sharp.test/mustache-sharp.test.csproj b/mustache-sharp.test/mustache-sharp.test.csproj
index 0457468..b0ae5bc 100644
--- a/mustache-sharp.test/mustache-sharp.test.csproj
+++ b/mustache-sharp.test/mustache-sharp.test.csproj
@@ -48,7 +48,7 @@
- {D71B378F-A4BA-4263-A4F0-07A49A0C528D}
+ {d71b378f-a4ba-4263-a4f0-07a49a0c528d}
mustache-sharp
diff --git a/mustache-sharp.vsmdi b/mustache-sharp.vsmdi
deleted file mode 100644
index c62973b..0000000
--- a/mustache-sharp.vsmdi
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/mustache-sharp/Properties/AssemblyInfo.cs b/mustache-sharp/Properties/AssemblyInfo.cs
index e6f709e..a70745c 100644
--- a/mustache-sharp/Properties/AssemblyInfo.cs
+++ b/mustache-sharp/Properties/AssemblyInfo.cs
@@ -34,6 +34,6 @@ using System.Runtime.CompilerServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("0.2.3.0")]
-[assembly: AssemblyFileVersion("0.2.3.0")]
+[assembly: AssemblyVersion("0.2.4.0")]
+[assembly: AssemblyFileVersion("0.2.4.0")]
[assembly: InternalsVisibleTo("mustache-sharp.test")]
\ No newline at end of file
diff --git a/mustache-sharp/PropertyDictionary.cs b/mustache-sharp/PropertyDictionary.cs
index eb6d66e..0bda944 100644
--- a/mustache-sharp/PropertyDictionary.cs
+++ b/mustache-sharp/PropertyDictionary.cs
@@ -2,6 +2,7 @@
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
+using System.Linq;
using System.Reflection;
namespace Mustache
@@ -40,23 +41,57 @@ namespace Mustache
if (!_cache.TryGetValue(type, out typeCache))
{
typeCache = new Dictionary>();
+
BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy;
- foreach (PropertyInfo propertyInfo in type.GetProperties(flags))
+
+ var properties = getMembers(type, type.GetProperties(flags).Where(p => !p.IsSpecialName));
+ foreach (PropertyInfo propertyInfo in properties)
{
- if (!propertyInfo.IsSpecialName)
- {
- typeCache.Add(propertyInfo.Name, i => propertyInfo.GetValue(i, null));
- }
+ typeCache.Add(propertyInfo.Name, i => propertyInfo.GetValue(i, null));
}
- foreach (FieldInfo fieldInfo in type.GetFields(flags))
+
+ var fields = getMembers(type, type.GetFields(flags).Where(f => !f.IsSpecialName));
+ foreach (FieldInfo fieldInfo in fields)
{
typeCache.Add(fieldInfo.Name, i => fieldInfo.GetValue(i));
}
+
_cache.Add(type, typeCache);
}
return typeCache;
}
+ private static IEnumerable getMembers(Type type, IEnumerable members)
+ where TMember : MemberInfo
+ {
+ var singles = from member in members
+ group member by member.Name into nameGroup
+ where nameGroup.Count() == 1
+ from property in nameGroup
+ select property;
+ var multiples = from member in members
+ group member by member.Name into nameGroup
+ where nameGroup.Count() > 1
+ select
+ (
+ from member in nameGroup
+ orderby getDistance(type, member)
+ select member
+ ).First();
+ var combined = singles.Concat(multiples);
+ return combined;
+ }
+
+ private static int getDistance(Type type, MemberInfo memberInfo)
+ {
+ int distance = 0;
+ for (; type != null && type != memberInfo.DeclaringType; type = type.BaseType)
+ {
+ ++distance;
+ }
+ return distance;
+ }
+
///
/// Gets the underlying instance.
///