Support public fields for keys
This commit is contained in:
parent
599dc7a78f
commit
517e38a6db
|
@ -452,6 +452,25 @@ Content";
|
|||
Assert.AreEqual(String.Empty, context[0].TagName, "The top-most context had the wrong tag type.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If a key refers to a public field, its value should be substituted in the output.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestGenerate_KeyRefersToPublicField_SubstitutesValue()
|
||||
{
|
||||
FormatCompiler compiler = new FormatCompiler();
|
||||
const string format = @"Hello, {{Field}}!!!";
|
||||
Generator generator = compiler.Compile(format);
|
||||
ClassWithPublicField instance = new ClassWithPublicField() { Field = "Bob" };
|
||||
string result = generator.Render(instance);
|
||||
Assert.AreEqual("Hello, Bob!!!", result, "The wrong text was generated.");
|
||||
}
|
||||
|
||||
public class ClassWithPublicField
|
||||
{
|
||||
public string Field;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Comment
|
||||
|
|
|
@ -8,7 +8,7 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyTitle("mustache-sharp.test")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyCompany("Truncon")]
|
||||
[assembly: AssemblyProduct("mustache-sharp.test")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2013")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
|
@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
|
|||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
[assembly: AssemblyVersion("0.2.2.0")]
|
||||
[assembly: AssemblyFileVersion("0.2.2.0")]
|
||||
[assembly: AssemblyVersion("0.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("0.0.0.0")]
|
||||
|
|
|
@ -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.2.0")]
|
||||
[assembly: AssemblyFileVersion("0.2.2.0")]
|
||||
[assembly: AssemblyVersion("0.2.3.0")]
|
||||
[assembly: AssemblyFileVersion("0.2.3.0")]
|
||||
[assembly: InternalsVisibleTo("mustache-sharp.test")]
|
|
@ -11,10 +11,10 @@ namespace Mustache
|
|||
/// </summary>
|
||||
internal sealed class PropertyDictionary : IDictionary<string, object>
|
||||
{
|
||||
private static readonly Dictionary<Type, Dictionary<string, PropertyInfo>> _cache = new Dictionary<Type, Dictionary<string, PropertyInfo>>();
|
||||
private static readonly Dictionary<Type, Dictionary<string, Func<object, object>>> _cache = new Dictionary<Type, Dictionary<string, Func<object, object>>>();
|
||||
|
||||
private readonly object _instance;
|
||||
private readonly Dictionary<string, PropertyInfo> _typeCache;
|
||||
private readonly Dictionary<string, Func<object, object>> _typeCache;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of a PropertyDictionary.
|
||||
|
@ -25,7 +25,7 @@ namespace Mustache
|
|||
_instance = instance;
|
||||
if (instance == null)
|
||||
{
|
||||
_typeCache = new Dictionary<string, PropertyInfo>();
|
||||
_typeCache = new Dictionary<string, Func<object, object>>();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -33,21 +33,25 @@ namespace Mustache
|
|||
}
|
||||
}
|
||||
|
||||
private static Dictionary<string, PropertyInfo> getCacheType(object instance)
|
||||
private static Dictionary<string, Func<object, object>> getCacheType(object instance)
|
||||
{
|
||||
Type type = instance.GetType();
|
||||
Dictionary<string, PropertyInfo> typeCache;
|
||||
Dictionary<string, Func<object, object>> typeCache;
|
||||
if (!_cache.TryGetValue(type, out typeCache))
|
||||
{
|
||||
typeCache = new Dictionary<string, PropertyInfo>();
|
||||
typeCache = new Dictionary<string, Func<object, object>>();
|
||||
BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy;
|
||||
foreach (PropertyInfo propertyInfo in type.GetProperties(flags))
|
||||
{
|
||||
if (!propertyInfo.IsSpecialName)
|
||||
{
|
||||
typeCache.Add(propertyInfo.Name, propertyInfo);
|
||||
typeCache.Add(propertyInfo.Name, i => propertyInfo.GetValue(i, null));
|
||||
}
|
||||
}
|
||||
foreach (FieldInfo fieldInfo in type.GetFields(flags))
|
||||
{
|
||||
typeCache.Add(fieldInfo.Name, i => fieldInfo.GetValue(i));
|
||||
}
|
||||
_cache.Add(type, typeCache);
|
||||
}
|
||||
return typeCache;
|
||||
|
@ -100,13 +104,13 @@ namespace Mustache
|
|||
/// <exception cref="System.ArgumentNullException">The name of the property was null.</exception>
|
||||
public bool TryGetValue(string key, out object value)
|
||||
{
|
||||
PropertyInfo propertyInfo;
|
||||
if (!_typeCache.TryGetValue(key, out propertyInfo))
|
||||
Func<object, object> getter;
|
||||
if (!_typeCache.TryGetValue(key, out getter))
|
||||
{
|
||||
value = null;
|
||||
return false;
|
||||
}
|
||||
value = getValue(propertyInfo);
|
||||
value = getter(_instance);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -117,11 +121,11 @@ namespace Mustache
|
|||
{
|
||||
get
|
||||
{
|
||||
ICollection<PropertyInfo> propertyInfos = _typeCache.Values;
|
||||
ICollection<Func<object, object>> getters = _typeCache.Values;
|
||||
List<object> values = new List<object>();
|
||||
foreach (PropertyInfo propertyInfo in propertyInfos)
|
||||
foreach (Func<object, object> getter in getters)
|
||||
{
|
||||
object value = getValue(propertyInfo);
|
||||
object value = getter(_instance);
|
||||
values.Add(value);
|
||||
}
|
||||
return values.AsReadOnly();
|
||||
|
@ -143,8 +147,8 @@ namespace Mustache
|
|||
{
|
||||
get
|
||||
{
|
||||
PropertyInfo propertyInfo = _typeCache[key];
|
||||
return getValue(propertyInfo);
|
||||
Func<object, object> getter = _typeCache[key];
|
||||
return getter(_instance);
|
||||
}
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
set
|
||||
|
@ -167,23 +171,23 @@ namespace Mustache
|
|||
|
||||
bool ICollection<KeyValuePair<string, object>>.Contains(KeyValuePair<string, object> item)
|
||||
{
|
||||
PropertyInfo propertyInfo;
|
||||
if (!_typeCache.TryGetValue(item.Key, out propertyInfo))
|
||||
Func<object, object> getter;
|
||||
if (!_typeCache.TryGetValue(item.Key, out getter))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
object value = getValue(propertyInfo);
|
||||
object value = getter(_instance);
|
||||
return Equals(item.Value, value);
|
||||
}
|
||||
|
||||
void ICollection<KeyValuePair<string, object>>.CopyTo(KeyValuePair<string, object>[] array, int arrayIndex)
|
||||
{
|
||||
List<KeyValuePair<string, object>> pairs = new List<KeyValuePair<string, object>>();
|
||||
ICollection<KeyValuePair<string, PropertyInfo>> collection = _typeCache;
|
||||
foreach (KeyValuePair<string, PropertyInfo> pair in collection)
|
||||
ICollection<KeyValuePair<string, Func<object, object>>> collection = _typeCache;
|
||||
foreach (KeyValuePair<string, Func<object, object>> pair in collection)
|
||||
{
|
||||
PropertyInfo propertyInfo = pair.Value;
|
||||
object value = getValue(propertyInfo);
|
||||
Func<object, object> getter = pair.Value;
|
||||
object value = getter(_instance);
|
||||
pairs.Add(new KeyValuePair<string, object>(pair.Key, value));
|
||||
}
|
||||
pairs.CopyTo(array, arrayIndex);
|
||||
|
@ -217,9 +221,10 @@ namespace Mustache
|
|||
/// <returns></returns>
|
||||
public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
|
||||
{
|
||||
foreach (KeyValuePair<string, PropertyInfo> pair in _typeCache)
|
||||
foreach (KeyValuePair<string, Func<object, object>> pair in _typeCache)
|
||||
{
|
||||
object value = getValue(pair.Value);
|
||||
Func<object, object> getter = pair.Value;
|
||||
object value = getter(_instance);
|
||||
yield return new KeyValuePair<string, object>(pair.Key, value);
|
||||
}
|
||||
}
|
||||
|
@ -228,10 +233,5 @@ namespace Mustache
|
|||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
private object getValue(PropertyInfo propertyInfo)
|
||||
{
|
||||
return propertyInfo.GetValue(_instance, null);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue