object GetMemberValue(string member) { var members = member.Split('.'); object context = null; for (var i = 0; i < members.Length; i++) { if (i == 0) { var parser = this.Parsers.SingleOrDefault(p => p.Name == members[i]); if (parser == null) { context = BlockParser.GetValue(this.Parsers.First().Context, members[i]); } else { context = parser.Context; } } else { context = BlockParser.GetValue(context, members[i]); } } return(context); }
public static string Parse(string template, object context, string contextName = "Context") { if (template == null || context == null || contextName == null) { throw new ArgumentNullException(); } var blockParser = new BlockParser(context, contextName); return(blockParser.Parse(template)); }
public string Parse(string block) { var resultBuilder = new StringBuilder(); var blockBuilder = new StringBuilder(); string forItem = null; System.Collections.IEnumerable forMembers = null; var ifParameters = new List <IfParameter>(); var blockStates = new Stack <BlockState>(); for (; ;) { var match = BlockMatcher.GetMatch(block); if (match == null) { if (blockStates.Count != 0) { throw new ConstructionException(); } resultBuilder.Append(block); return(resultBuilder.ToString().UnescapeTemplate()); } if (blockStates.Count == 0) { resultBuilder.Append(block.Substring(0, match.Match.Index)); } else { blockBuilder.Append(block.Substring(0, match.Match.Index)); } block = block.Substring(match.Match.Index + match.Match.Length, block.Length - match.Match.Index - match.Match.Length); switch (match.Type) { case BlockType.Tag: if (blockStates.Count == 0) { var member = match.Match.Groups["member"]; if (member.Success) { resultBuilder.Append(this.GetMemberValue(member.Value)); } else { throw new InvalidOperationException(); } } else { blockBuilder.Append(match.Match.Value); } break; case BlockType.If: if (blockStates.Count == 0) { ifParameters.Clear(); blockBuilder = new StringBuilder(); var member = match.Match.Groups["member"]; var value = match.Match.Groups["value"]; var parameter = new IfParameter(); parameter.Member = this.GetMemberValue(member.Value); parameter.Value = value.Success ? value.Value.UnescapeValue() : null; parameter.IsElse = false; ifParameters.Add(parameter); } else { blockBuilder.Append(match.Match.Value); } blockStates.Push(BlockState.If); break; case BlockType.ElseIf: if (blockStates.Count == 0 || blockStates.Peek() != BlockState.If) { throw new ConstructionException(); } else if (blockStates.Count == 1) { ifParameters.Last().Block = blockBuilder.ToString(); blockBuilder = new StringBuilder(); var member = match.Match.Groups["member"]; var value = match.Match.Groups["value"]; var parameter = new IfParameter(); parameter.Member = this.GetMemberValue(member.Value); parameter.Value = value.Success ? value.Value.UnescapeValue() : null; parameter.IsElse = false; ifParameters.Add(parameter); } else { blockBuilder.Append(match.Match.Value); } break; case BlockType.Else: if (blockStates.Count == 0 || blockStates.Peek() != BlockState.If) { throw new ConstructionException(); } else if (blockStates.Count == 1) { ifParameters.Last().Block = blockBuilder.ToString(); blockBuilder = new StringBuilder(); var parameter = new IfParameter(); parameter.Member = null; parameter.Value = null; parameter.IsElse = true; ifParameters.Add(parameter); } else { blockBuilder.Append(match.Match.Value); } break; case BlockType.EndIf: if (blockStates.Count == 0 || blockStates.Peek() != BlockState.If) { throw new ConstructionException(); } else if (blockStates.Count == 1) { ifParameters.Last().Block = blockBuilder.ToString(); blockBuilder = null; foreach (var ifParameter in ifParameters) { var matched = false; if (ifParameter.IsElse) { matched = true; } else if (ifParameter.Value == null) { if (ifParameter.Member != null && !ifParameter.Member.Equals(ifParameter.Member.GetType().GetDefault())) { matched = true; } } else { if (ifParameter.Member != null && ifParameter.Member.ToString() == ifParameter.Value) { matched = true; } } if (matched) { var parser = new BlockParser(this.Context, this.Name, this._parsers); resultBuilder.Append(parser.Parse(ifParameter.Block)); break; } } } else { blockBuilder.Append(match.Match.Value); } blockStates.Pop(); break; case BlockType.For: if (blockStates.Count == 0) { blockBuilder = new StringBuilder(); var item = match.Match.Groups["item"]; var list = match.Match.Groups["list"]; forItem = item.Value; forMembers = this.GetMemberValue(list.Value) as System.Collections.IEnumerable; } else { blockBuilder.Append(match.Match.Value); } blockStates.Push(BlockState.For); break; case BlockType.EndFor: if (blockStates.Count == 0 || blockStates.Peek() != BlockState.For) { throw new ConstructionException(); } else if (blockStates.Count == 1) { if (forMembers != null) { var forBlock = blockBuilder.ToString(); var members = new List <object>(); foreach (var forMember in forMembers) { members.Add(forMember); } for (var i = 0; i < members.Count; i++) { var parsers = this._parsers.ToList(); parsers.Add(this); var context = new ParserContext(members[i]); context.Dictionary["IsFirst"] = i == 0; context.Dictionary["IsLast"] = i == members.Count - 1; context.Dictionary["ForIndex"] = i; context.Dictionary["ForCount"] = members.Count; var parser = new BlockParser(context, forItem, parsers); resultBuilder.Append(parser.Parse(forBlock)); } } } else { blockBuilder.Append(match.Match.Value); } blockStates.Pop(); break; default: throw new NotSupportedException(); } } }