using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
namespace Mustache
{
///
/// Provides methods for creating instances of PropertyDictionary.
///
internal sealed class PropertyDictionary : IDictionary
{
private static readonly Dictionary> _cache = new Dictionary>();
private readonly object _instance;
private readonly Dictionary _typeCache;
///
/// Initializes a new instance of a PropertyDictionary.
///
/// The instance to wrap in the PropertyDictionary.
public PropertyDictionary(object instance)
{
_instance = instance;
if (instance == null)
{
_typeCache = new Dictionary();
}
else
{
_typeCache = getCacheType(_instance);
}
}
private static Dictionary getCacheType(object instance)
{
Type type = instance.GetType();
Dictionary typeCache;
if (!_cache.TryGetValue(type, out typeCache))
{
typeCache = new Dictionary();
BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy;
foreach (PropertyInfo propertyInfo in type.GetProperties(flags))
{
if (!propertyInfo.IsSpecialName)
{
typeCache.Add(propertyInfo.Name, propertyInfo);
}
}
_cache.Add(type, typeCache);
}
return typeCache;
}
///
/// Gets the underlying instance.
///
public object Instance
{
get { return _instance; }
}
[EditorBrowsable(EditorBrowsableState.Never)]
void IDictionary.Add(string key, object value)
{
throw new NotSupportedException();
}
///
/// Determines whether a property with the given name exists.
///
/// The name of the property.
/// True if the property exists; otherwise, false.
public bool ContainsKey(string key)
{
return _typeCache.ContainsKey(key);
}
///
/// Gets the name of the properties in the type.
///
public ICollection Keys
{
get { return _typeCache.Keys; }
}
[EditorBrowsable(EditorBrowsableState.Never)]
bool IDictionary.Remove(string key)
{
throw new NotSupportedException();
}
///
/// Tries to get the value for the given property name.
///
/// The name of the property to get the value for.
/// The variable to store the value of the property or the default value if the property is not found.
/// True if a property with the given name is found; otherwise, false.
/// The name of the property was null.
public bool TryGetValue(string key, out object value)
{
PropertyInfo propertyInfo;
if (!_typeCache.TryGetValue(key, out propertyInfo))
{
value = null;
return false;
}
value = getValue(propertyInfo);
return true;
}
///
/// Gets the values of all of the properties in the object.
///
public ICollection