小鬼之家

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

  博客园 :: 首页 :: 联系 :: 订阅 订阅 :: 管理
  56 Posts :: 0 Stories :: 63 Comments :: 1 Trackbacks
  昨天发了一篇关于模板的功能介绍的文章,今天我想说说我为什么想设计一个自己的模板分析程序而不愿意使用微软老大给我们做好的近似完美的一切.
  做网站的本质无非是一些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