using System; using System.Collections.Generic; using System.Globalization; using mustache.Properties; namespace mustache { /// /// Represents a scope of keys. /// public sealed class KeyScope { private readonly object _source; private readonly KeyScope _parent; /// /// Initializes a new instance of a KeyScope. /// /// The object to search for keys in. internal KeyScope(object source) : this(source, null) { } /// /// Initializes a new instance of a KeyScope. /// /// The object to search for keys in. /// The parent scope to search in if the value is not found. internal KeyScope(object source, KeyScope parent) { _parent = parent; _source = source; } /// /// Creates a child scope that searches for keys in the given object. /// /// The object to search for keys in. /// The new child scope. public KeyScope CreateChildScope(object source) { KeyScope scope = new KeyScope(source, this); return scope; } /// /// Attempts to find the value associated with the key with given name. /// /// The name of the key. /// The value associated with the key with the given name. /// A key with the given name could not be found. internal object Find(string name) { string[] names = name.Split('.'); string member = names[0]; object nextLevel = _source; if (member != "this") { nextLevel = find(member); } for (int index = 1; index < names.Length; ++index) { IDictionary context = toLookup(nextLevel); member = names[index]; nextLevel = context[member]; } return nextLevel; } private object find(string name) { IDictionary lookup = toLookup(_source); if (lookup.ContainsKey(name)) { return lookup[name]; } if (_parent == null) { string message = String.Format(CultureInfo.CurrentCulture, Resources.KeyNotFound, name); throw new KeyNotFoundException(message); } return _parent.find(name); } private static IDictionary toLookup(object value) { IDictionary lookup = value as IDictionary; if (lookup == null) { lookup = new PropertyDictionary(value); } return lookup; } } }