2013-04-18 23:26:58 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Globalization;
|
2013-04-19 12:56:21 +00:00
|
|
|
|
using System.Linq;
|
2013-04-18 23:26:58 +00:00
|
|
|
|
using mustache.Properties;
|
|
|
|
|
|
|
|
|
|
namespace mustache
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Represents a scope of keys.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public sealed class KeyScope
|
|
|
|
|
{
|
|
|
|
|
private readonly object _source;
|
|
|
|
|
private readonly KeyScope _parent;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Initializes a new instance of a KeyScope.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="source">The object to search for keys in.</param>
|
|
|
|
|
internal KeyScope(object source)
|
|
|
|
|
: this(source, null)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Initializes a new instance of a KeyScope.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="source">The object to search for keys in.</param>
|
|
|
|
|
/// <param name="parent">The parent scope to search in if the value is not found.</param>
|
|
|
|
|
internal KeyScope(object source, KeyScope parent)
|
|
|
|
|
{
|
|
|
|
|
_parent = parent;
|
|
|
|
|
_source = source;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Occurs when a key/property is not found in the object graph.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public event EventHandler<MissingKeyEventArgs> KeyNotFound;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Creates a child scope that searches for keys in the given object.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="source">The object to search for keys in.</param>
|
|
|
|
|
/// <returns>The new child scope.</returns>
|
|
|
|
|
public KeyScope CreateChildScope(object source)
|
|
|
|
|
{
|
|
|
|
|
KeyScope scope = new KeyScope(source, this);
|
|
|
|
|
scope.KeyNotFound = KeyNotFound;
|
|
|
|
|
return scope;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Attempts to find the value associated with the key with given name.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="name">The name of the key.</param>
|
|
|
|
|
/// <returns>The value associated with the key with the given name.</returns>
|
|
|
|
|
/// <exception cref="System.Collections.Generic.KeyNotFoundException">A key with the given name could not be found.</exception>
|
|
|
|
|
internal object Find(string name)
|
|
|
|
|
{
|
|
|
|
|
string[] names = name.Split('.');
|
|
|
|
|
string member = names[0];
|
|
|
|
|
object nextLevel = _source;
|
|
|
|
|
if (member != "this")
|
|
|
|
|
{
|
2013-04-19 12:56:21 +00:00
|
|
|
|
nextLevel = find(name, member);
|
2013-04-18 23:26:58 +00:00
|
|
|
|
}
|
|
|
|
|
for (int index = 1; index < names.Length; ++index)
|
|
|
|
|
{
|
|
|
|
|
IDictionary<string, object> context = toLookup(nextLevel);
|
|
|
|
|
member = names[index];
|
2013-04-19 12:56:21 +00:00
|
|
|
|
if (!context.TryGetValue(member, out nextLevel))
|
|
|
|
|
{
|
|
|
|
|
nextLevel = handleKeyNotFound(name, member);
|
|
|
|
|
}
|
2013-04-18 23:26:58 +00:00
|
|
|
|
}
|
|
|
|
|
return nextLevel;
|
|
|
|
|
}
|
|
|
|
|
|
2013-04-19 12:56:21 +00:00
|
|
|
|
private object find(string fullName, string memberName)
|
2013-04-18 23:26:58 +00:00
|
|
|
|
{
|
|
|
|
|
IDictionary<string, object> lookup = toLookup(_source);
|
2013-04-19 12:56:21 +00:00
|
|
|
|
if (lookup.ContainsKey(memberName))
|
2013-04-18 23:26:58 +00:00
|
|
|
|
{
|
2013-04-19 12:56:21 +00:00
|
|
|
|
return lookup[memberName];
|
2013-04-18 23:26:58 +00:00
|
|
|
|
}
|
|
|
|
|
if (_parent == null)
|
|
|
|
|
{
|
2013-04-19 12:56:21 +00:00
|
|
|
|
return handleKeyNotFound(fullName, memberName);
|
|
|
|
|
}
|
|
|
|
|
return _parent.find(fullName, memberName);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private object handleKeyNotFound(string fullName, string memberName)
|
|
|
|
|
{
|
|
|
|
|
MissingKeyEventArgs args = new MissingKeyEventArgs(fullName, memberName);
|
|
|
|
|
if (KeyNotFound != null)
|
|
|
|
|
{
|
|
|
|
|
KeyNotFound(this, args);
|
|
|
|
|
}
|
|
|
|
|
if (args.Handled)
|
|
|
|
|
{
|
|
|
|
|
return args.Substitute;
|
2013-04-18 23:26:58 +00:00
|
|
|
|
}
|
2013-04-19 12:56:21 +00:00
|
|
|
|
string message = String.Format(CultureInfo.CurrentCulture, Resources.KeyNotFound, memberName);
|
|
|
|
|
throw new KeyNotFoundException(message);
|
2013-04-18 23:26:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static IDictionary<string, object> toLookup(object value)
|
|
|
|
|
{
|
|
|
|
|
IDictionary<string, object> lookup = value as IDictionary<string, object>;
|
|
|
|
|
if (lookup == null)
|
|
|
|
|
{
|
|
|
|
|
lookup = new PropertyDictionary(value);
|
|
|
|
|
}
|
|
|
|
|
return lookup;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|