Binding WalkTo(SymbolExpression expression, out string[] missingTokens) { ValidateNoRecursion(expression); symbolStack.Push(expression); try { var val = binding; missingTokens = new string[0]; //any indexers that are lookups, do them now so we are in the right context //take a copy so the lookup version remains for later use expression = new SymbolExpression(expression.Steps.Select(s => { var indexer = s as Indexer; if (indexer != null && indexer.IsSymbol) { string[] missing; var index = WalkTo(indexer.Symbol, out missing); return(new Indexer(index.Item)); } return(s); })); foreach (var step in expression.Steps) { var iss = step as Identifier; if (iss != null) { if (val.TryGetValue(iss.Text, out val)) { continue; } } else { var ix = step as Indexer; if (ix != null && !ix.IsSymbol) { if (ix.Index == "*" && val.Indexable.Count > 0) { val = val.Indexable.First().Value; continue; } if (val.Indexable.TryGetValue(ix.Index, out val)) { continue; } } else { throw new NotImplementedException("Unknown step type: " + step); } } if (parent == null) { return(null); } return(parent.WalkTo(expression, out missingTokens)); } if (val != null && val.Item != null) { Template template; string error; if (TemplateParser.TryParseTemplate(val.Item, out template, out error)) { using (var x = new StringWriter()) { var context = new EvaluationContext(new Binding(), x, this); TemplateEvaluator.Evaluate(template, context, out missingTokens); x.Flush(); return(new Binding(x.ToString())); } } } return(val); } finally { symbolStack.Pop(); } }
public static void Evaluate(Template template, Binding properties, TextWriter output, out string[] missingTokens) { var context = new EvaluationContext(properties, output); Evaluate(template, context, out missingTokens); }
public EvaluationContext(Binding binding, TextWriter output, EvaluationContext parent = null) { this.binding = binding; this.output = output; this.parent = parent; }