示例#1
0
        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);
        }
示例#2
0
        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));
        }
示例#3
0
        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();
                }
            }
        }