小鬼之家

流浪,游走于文明与原始之间. 关注底层技术,实现美好生活。

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
  昨天发了一篇关于模板的功能介绍的文章,今天我想说说我为什么想设计一个自己的模板分析程序而不愿意使用微软老大给我们做好的近似完美的一切.
  做网站的本质无非是一些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    }
posted on 2007-08-24 20:59  黄尚  阅读(3230)  评论(8编辑  收藏  举报