Created
August 22, 2012 23:15
-
-
Save volgar1x/3430475 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Tree<TKey, TValue> | |
{ | |
protected readonly Tree<TKey, TValue> parent; | |
protected readonly IDictionary<TKey, Tree<TKey, TValue>> children = new Dictionary<TKey, Tree<TKey, TValue>>(); | |
public Tree(Tree<TKey, TValue> parent) { | |
this.parent = parent; | |
} | |
public Tree() { | |
this(null); | |
} | |
public Tree<TKey, TValue> Parent { get { return parent; } } | |
public TKey Key { get; set; } | |
public TValue Value { get; set; } | |
public TValue this[IEnumerable<TKey>] { | |
get { | |
return Get(value); | |
} | |
} | |
protected Tree<TKey, TValue> GetChildOrCreate(TKey key) { | |
Tree<TKey, TValue> child = children[key]; | |
if (child == null) { | |
child = new Tree<TKey, TValue>(this); | |
children.Add(key, child); | |
} | |
return child; | |
} | |
public TValue Get(IEnumerable<TKey> keys) { | |
if (keys.Count() <= 0) { | |
return Value; | |
} | |
Tree<TKey, TValue> child = children[keys.First()]; | |
if (child != null) { | |
return child.Get(keys.Skip(1)); // http://msdn.microsoft.com/en-us/library/bb358985.aspx | |
} | |
else if (parent != null) { | |
return parent.Value; | |
} | |
return null; | |
} | |
public Tree<TKey, TValue> Get(TKey key) { | |
return child[key]; | |
} | |
public void Add(IEnumerable<TKey> keys, TValue value) { | |
TKey key = keys.First(); | |
Tree<TKey, TValue> child = GetChildOrCreate(key); | |
if (keys.Count() > 0) { | |
child.Add(keys.Skip(1), value); | |
} else { | |
child.Value = value; | |
} | |
} | |
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() { | |
return new TreeEnumerator<TKey, TValue>(this); | |
} | |
public IEnumerable<KeyValuePair<TKey, TValue>> Enumerate() { | |
if (Key != null) { | |
yield return new KeyValuePair<TKey, TValue>(Key, Value); | |
} | |
foreach (KeyValuePair<TKey, Tree<TKey, TValue>> entry : children) { | |
entry.Enumerate(); | |
} | |
} | |
} | |
class CompilableTree<TKey, TValue> : Tree<TKey, TValue> { | |
protected Expression KeyExpression { | |
get { | |
return Expression.Property(Expression.Constant(this), "Key"); | |
} | |
} | |
protected Expression ValueExpression { | |
get { | |
return Expression.Property(Expression.Constant(this), "Value"); | |
} | |
} | |
protected SwitchCase ToSwitchCase(Expression ret, Expression param, int level) { | |
if (Value != null) { | |
return Expression.SwitchCase( | |
Expression.Return( | |
ret, | |
ValueExpression | |
), | |
KeyExpression | |
); | |
} else { | |
return Expression.SwitchCase( | |
Compile(ret, param, level), | |
KeyExpression | |
); | |
} | |
} | |
private static readonly MethodInfo ELEMENT_AT = | |
typeof(Enumerable).GetMethod( | |
"ElementAt", | |
typeof(IEnumerable<TKey>), | |
typeof(int) | |
); | |
protected SwitchExpression Compile(Expression ret, Expression param, int level = 0) { | |
return Expression.Switch( | |
Expression.Call(ELEMENT_AT, param, level), | |
Expression.Return(ret, Expression.Constant(null)), // return null by default | |
children.Values.Select(x => x.ToSwitchCase(ret, param, level + 1)).ToArray() | |
); | |
} | |
public Func<IEnumerable<TKey>, TValue> Compile() { | |
Expression ret = Expression.Label(), param = Expression.Parameter(typeof(IEnumerable<TKey>)); | |
Expression body = Compile(ret, e); | |
return Expression.Lambda<Func<IEnumerable<TKey>, TValue>>(body).Compile(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment