zoukankan      html  css  js  c++  java
  • 我的模板分析引擎类PHP的.net开发方法功能实现篇

      昨天发了一篇关于模板的功能介绍的文章,今天我想说说我为什么想设计一个自己的模板分析程序而不愿意使用微软老大给我们做好的近似完美的一切.
      做网站的本质无非是一些html加一点点css,再放一些Js做调料,这加工出来的就是各种各样的网站平台;但微软老大却先把html和css做成美国大汉堡,再把JS弄成根香肠提供给广大的食客。虽然大家都喜欢这种大餐,但吃多也终究不是很好,而且有时候我们需要的是一份简单的农家小炒,所以我就通过几天的努力让自己重新有机会直接与HTML、CSS、JS等打交道。
          前面有朋友说我只是把<asp:Repeater id="rptTables" > 换成了{repeater rptTables},虽然我当时不太同意这种说法,但细想一下其实这种说法也是对的。这所以要把<asp:Repeater id="rptTables" > 换成{repeater rptTables},是因为后者比前者更容易分析。也有朋友说我是用另一种方式重新实现了另一种ASP.NET控件,其实这也是正确的,ASP.NET控件的好处和使用方式已经是广大.NET程序员所熟悉的东东,为了使别人看到我的方案不至于不知所谓,我也只能实现和它差不多的方案,而且我知道我要的是直接与最原始的原素打交道的权力,而不是要去否定别的方案和形式。
          说了这么多,应该开始说说我的代码了,以下是模板分析的主要代码片段,具体的分析我会在后续的文章中进行说明。
      1internal class Template : IUI.ITemplate
      2    {
      3        bool _isInstantiateIn = false;
      4        private Dictionary<string, UIModel.Control> dicContainer;
      5        private List<Control> listContainer;
      6        private List<Token> tokens;
      7        private char[] chrs;
      8
      9        public Template()
     10        {
     11            dicContainer = new Dictionary<string, Control>();
     12            listContainer = new List<Control>();
     13            tokens = new List<Token>();
     14        }

     15
     16        public void InstantiateIn(ref string input)
     17        {
     18            _isInstantiateIn = true;
     19            chrs = input.ToCharArray();
     20
     21            InitTokens(chrs);
     22
     23            GroupTokens();
     24
     25            InitTags();
     26        }

     27
     28        public bool ContainsKey(string id)
     29        {
     30            return dicContainer.ContainsKey(id);
     31        }

     32
     33        public Ctit.TTCCostPro.UIModel.Control FindControl(string id)
     34        {
     35            if (dicContainer.ContainsKey(id))
     36            {
     37                return dicContainer[id];
     38            }

     39            else
     40            {
     41                return null;
     42            }

     43        }

     44
     45        public string Render()
     46        {
     47            if (!_isInstantiateIn)
     48                throw new Exception("Template must InstantiateIn before render!!");
     49
     50            //StringBuilder sb = new StringBuilder();
     51
     52            //for (int i = 0; i < tokens.Count; i++)
     53            //{
     54            //    sb.AppendFormat("First: {0}, Second: {1}, StartIndex: {2}, EndIndex: {3} TokenType: {4} InnerStart: {5}, InnerEnd: {6} <br />", tokens[i].First, tokens[i].Second, tokens[i].StartIndex, tokens[i].EndIndex, tokens[i].TokenType.ToString(), tokens[i].InnerStart, tokens[i].InnerEnd);
     55            //}
     56            //return sb.ToString();
     57
     58            StringBuilder sb = new StringBuilder();
     59
     60            int k = 0;
     61
     62            for (int i = 0; i < listContainer.Count; i++)
     63            {
     64                while (k < listContainer[i].StartIndex && k < chrs.Length)
     65                {
     66                    sb.Append(chrs[k]);
     67                    k++;
     68                }

     69
     70                if (listContainer[i].Display)
     71                {
     72                    StringBuilder sHtml = new StringBuilder();
     73                    RenderControl(listContainer[i], sHtml);
     74                    sb.Append(sHtml);
     75                }

     76                k = listContainer[i].EndIndex + 1;
     77            }

     78
     79            while (k < chrs.Length)
     80            {
     81                sb.Append(chrs[k++]);
     82            }

     83
     84            return sb.ToString();
     85        }

     86
     87        private void RenderControl(Control ctr, StringBuilder sHtml)
     88        {
     89            switch (ctr.TagName.ToLower())
     90            {
     91                case "repeater":
     92                    {
     93                        Repeater rpt = (Repeater)ctr;
     94
     95
     96                        if (rpt.DataSource != null)
     97                        {
     98                            CreateInnerTemplate(sHtml, rpt, rpt.HeaderTemplate);
     99                            IEnumerable date = (IEnumerable)rpt.DataSource;
    100
    101                            foreach (object o in date)
    102                            {
    103                                rpt.Current = new Dictionary<stringstring>();
    104                                PropertyInfo[] properties = o.GetType().GetProperties();
    105                                foreach (PropertyInfo p in properties)
    106                                {
    107                                    rpt.Current.Add(p.Name, p.GetValue(o, null).ToString());
    108                                }

    109                                CreateInnerTemplate(sHtml, rpt, rpt.ItemTemplate);
    110                            }

    111
    112                            CreateInnerTemplate(sHtml, rpt, rpt.FooterTemplate);
    113                        }

    114
    115                        break;
    116                    }

    117                case "view":
    118                    {
    119                        break;
    120                    }

    121                case "eval":
    122                    {
    123                        TextControl eval = (TextControl)ctr;
    124                        if (eval.ParentNode.Current.ContainsKey(eval.Second))
    125                        {
    126                            sHtml.Append(eval.ParentNode.Current[eval.Second]);
    127                        }

    128                        break;
    129                    }

    130                default:
    131                    {
    132                        break;
    133                    }

    134            }

    135        }

    136
    137        private void CreateInnerTemplate(StringBuilder sHtml, Repeater rpt, InnerIndex inner)
    138        {
    139            if (Controls.HadChildTag(inner, rpt))
    140            {
    141                List<Control> ls = Controls.GetChildNodes(inner, rpt);
    142                int k = inner.InnerStart;
    143
    144                for (int i = 0; i < ls.Count; i++)
    145                {
    146                    while (k < ls[i].StartIndex && k < inner.InnerEnd)
    147                    {
    148                        sHtml.Append(chrs[k++]);
    149                    }

    150
    151                    if (ls[i].Display == true)
    152                    {
    153                        RenderControl(ls[i], sHtml);
    154                    }

    155
    156                    k = ls[i].EndIndex + 1;
    157                }

    158
    159                while (k < inner.InnerEnd)
    160                {
    161                    sHtml.Append(chrs[k++]);
    162                }

    163            }

    164            else
    165            {
    166                CharsManager.Copy(chrs, inner, sHtml);
    167            }

    168        }

    169
    170        private void AddSingleTag(Control parentNode, Token token)
    171        {
    172            switch (token.First.ToLower())
    173            {
    174                case "page":
    175                case "eval":
    176                    {
    177                        TextControl textInfo = new TextControl();
    178                        textInfo.StartIndex = token.StartIndex;
    179                        textInfo.EndIndex = token.EndIndex;
    180                        textInfo.First = token.First;
    181                        textInfo.Second = token.Second;
    182                        textInfo.ParentNode = parentNode;
    183                        textInfo.TagName = token.First;
    184
    185                        //把根结点元素放在列表容器里面去.
    186                        if (parentNode == null)
    187                        {
    188                            listContainer.Add(textInfo);
    189                        }

    190                        else//子结点放在父结点下面
    191                        {
    192                            parentNode.AppendChild(textInfo);
    193                        }

    194                        break;
    195                    }

    196                default:
    197                    break;
    198            }

    199        }

    200
    201        private void AddComplexTag(Control parentNode, ref int index)
    202        {
    203            if (index >= tokens.Count)
    204                return;
    205
    206            Token token = tokens[index];
    207
    208            switch (token.First.ToLower())
    209            {
    210                case "repeater":
    211                    {
    212                        Repeater rpt = new Repeater();
    213                        rpt.Id = token.Second;
    214                        rpt.StartIndex = token.StartIndex;
    215                        rpt.EndIndex = token.EndIndex;
    216                        rpt.ParentNode = parentNode;
    217                        rpt.TagName = token.First;
    218
    219                        while (++index < tokens.Count && tokens[index].EndIndex != token.EndIndex)
    220                        {
    221                            if (tokens[index].TokenType == TokenType.Single)
    222                            {
    223                                AddSingleTag(rpt, tokens[index]);
    224                            }

    225                            else if (tokens[index].TokenType == TokenType.CloseBegin)
    226                            {
    227                                switch (tokens[index].First.ToLower())
    228                                {
    229                                    case "headertemplate":
    230                                        {
    231                                            rpt.HeaderTemplate.InnerStart = tokens[index].InnerStart;
    232                                            rpt.HeaderTemplate.InnerEnd = tokens[index].InnerEnd;
    233                                            break;
    234                                        }

    235                                    case "itemtemplate":
    236                                        {
    237                                            rpt.ItemTemplate.InnerStart = tokens[index].InnerStart;
    238                                            rpt.ItemTemplate.InnerEnd = tokens[index].InnerEnd;
    239                                            break;
    240                                        }

    241                                    case "alternatingitemtemplate":
    242                                        {
    243                                            rpt.AlternatingItemTemplate.InnerStart = tokens[index].InnerStart;
    244                                            rpt.AlternatingItemTemplate.InnerEnd = tokens[index].InnerEnd;
    245                                            break;
    246                                        }

    247                                    case "separatortemplate":
    248                                        {
    249                                            rpt.SeparatorTemplate.InnerStart = tokens[index].InnerStart;
    250                                            rpt.SeparatorTemplate.InnerEnd = tokens[index].InnerEnd;
    251                                            break;
    252                                        }

    253                                    case "footertemplate":
    254                                        {
    255                                            rpt.FooterTemplate.InnerStart = tokens[index].InnerStart;
    256                                            rpt.FooterTemplate.InnerEnd = tokens[index].InnerEnd;
    257                                            break;
    258                                        }

    259                                    default:
    260                                        break;
    261                                }

    262                            }

    263                            else if (tokens[index].TokenType == TokenType.ComplexBegin)
    264                            {
    265                                AddComplexTag(rpt, ref index);
    266                            }

    267                        }

    268
    269                        if (parentNode != null)
    270                        {
    271                            parentNode.AppendChild(rpt);
    272                        }

    273                        else
    274                        {
    275                            listContainer.Add(rpt);
    276                        }

    277
    278                        if (!dicContainer.ContainsKey(rpt.Id))
    279                        {
    280                            dicContainer.Add(rpt.Id, rpt);
    281                        }

    282#if DEBUG
    283                        else
    284                        {
    285                            throw new Exception(string.Format("Another control in this page already uses id: {0}", rpt.Id));
    286                        }

    287#endif
    288                        break;
    289                    }

    290                case "view":
    291                    {
    292                        break;
    293                    }

    294                default:
    295                    break;
    296            }

    297        }

    298
    299        private void InitTags()
    300        {
    301            for (int i = 0; i < tokens.Count; i++)
    302            {
    303                Token token = tokens[i];
    304                if (token.TokenType == TokenType.Single)
    305                {
    306                    AddSingleTag(null, token);
    307                }

    308                else if (token.TokenType == TokenType.ComplexBegin)
    309                {
    310                    AddComplexTag(nullref i);
    311                }

    312            }

    313        }

    314
    315        private void InitTokens(char[] chrs)
    316        {
    317            for (int i = 0; i < chrs.Length; i++)
    318            {
    319                if (chrs[i] == '{' && (i == 0 || chrs[i - 1!= '\\'))
    320                {
    321                    Token token = new Token();
    322                    token.StartIndex = i;
    323
    324                    if (chrs[i + 1== '/')
    325                    {
    326                        if (++>= chrs.Length)
    327                            break;
    328
    329                        Pair<stringstring> p = Tags.GetTag(chrs, ref i);
    330                        token.First = p.First;
    331                        token.Second = p.Second;
    332                        token.TokenType = GetTokenType(token.First, true);
    333                    }

    334                    else
    335                    {
    336                        Pair<stringstring> p = Tags.GetTag(chrs, ref i);
    337                        token.First = p.First;
    338                        token.Second = p.Second;
    339                        token.TokenType = GetTokenType(token.First, false);
    340                    }

    341
    342                    token.EndIndex = i;
    343                    tokens.Add(token);
    344                }

    345            }

    346        }

    347
    348        private void GroupTokens()
    349        {
    350            Stack<Token> s = new Stack<Token>();
    351
    352            for (int i = 0; i < tokens.Count; i++)
    353            {
    354                if (tokens[i].TokenType == TokenType.ComplexBegin || tokens[i].TokenType == TokenType.CloseBegin )
    355                {
    356                    s.Push(tokens[i]);
    357                }

    358                else if (tokens[i].TokenType == TokenType.ComplexEnd || tokens[i].TokenType == TokenType.CloseEnd)
    359                {
    360                    if (string.Compare(tokens[i].First, s.Peek().First) == 0)
    361                    {
    362                        Token token = s.Pop();
    363                        token.InnerStart = token.EndIndex + 1;
    364                        token.InnerEnd = tokens[i].StartIndex;
    365                        token.EndIndex = tokens[i].EndIndex;
    366                    }

    367                    else
    368                    {
    369                        s.Push(tokens[i]);
    370                    }

    371                }

    372            }

    373
    374            if (s.Count != 0)
    375            {
    376                throw new Exception("Tags do not match, please check your template file.");
    377            }

    378        }

    379
    380        private TokenType GetTokenType(string tagName, bool isEnd)
    381        {
    382            TagType tagType = TagTypeManager.GetTagType(tagName);
    383            TokenType tokenType = new TokenType();
    384
    385            if (isEnd)
    386            {
    387                if (tagType == TagType.Close)
    388                {
    389                    tokenType = TokenType.CloseEnd;
    390                }

    391                else if (tagType == TagType.Complex)
    392                {
    393                    tokenType = TokenType.ComplexEnd;
    394                }

    395                else
    396                {
    397                    tokenType = TokenType.NotToken;
    398                }

    399            }

    400            else
    401            {
    402                if (tagType == TagType.Close)
    403                {
    404                    tokenType = TokenType.CloseBegin;
    405                }

    406                else if (tagType == TagType.Complex)
    407                {
    408                    tokenType = TokenType.ComplexBegin;
    409                }

    410                else if (tagType == TagType.Single)
    411                {
    412                    tokenType = TokenType.Single;
    413                }

    414                else
    415                {
    416                    tokenType = TokenType.NotToken;
    417                }

    418            }

    419
    420            return tokenType;
    421        }

    422    }
  • 相关阅读:
    CSS3——复杂选择器
    单元测试覆盖率设置
    你必须了解的「架构」小历史
    js正则表达式:学习网址和部分正则验证
    转: js实现全角半角检测的方法
    Linux and the Unix Philosophy(1)
    HTML DOM 对象
    理解css中的 content:" " 是什么意思
    JS
    js
  • 原文地址:https://www.cnblogs.com/afxcn/p/868874.html
Copyright © 2011-2022 走看看