Wed Feb 24 15:47:16 CET 2010 Paolo Molaro <lupus@ximian.com>
[mono.git] / mcs / class / System.Web / System.Web.UI / ControlBuilder.cs
1 //
2 // System.Web.UI.ControlBuilder.cs
3 //
4 // Authors:
5 //      Duncan Mak  (duncan@ximian.com)
6 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 //      Marek Habersack <mhabersack@novell.com>
8 //
9 // (C) 2002, 2003 Ximian, Inc. (http://www.ximian.com)
10 // Copyright (C) 2005-2010 Novell, Inc (http://www.novell.com)
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 using System.Collections;
33 using System.Configuration;
34 using System.CodeDom;
35 using System.Globalization;
36 using System.Reflection;
37 using System.Security.Permissions;
38 using System.Web.Compilation;
39 using System.Web.Configuration;
40 using System.IO;
41 using System.Web.UI.WebControls;
42 using System.Web.Util;
43
44 using _Location = System.Web.Compilation.Location;
45
46 namespace System.Web.UI {
47
48         // CAS
49         [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
50         [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
51         public class ControlBuilder
52         {
53                 internal static readonly BindingFlags FlagsNoCase = BindingFlags.Public |
54                         BindingFlags.Instance |
55                         BindingFlags.Static |
56                         BindingFlags.IgnoreCase;
57
58                 ControlBuilder myNamingContainer;
59                 TemplateParser parser;
60                 Type parserType;
61                 ControlBuilder parentBuilder;
62                 Type type;             
63                 string tagName;
64                 string originalTagName;
65                 string id;
66                 IDictionary attribs;
67                 int line;
68                 string fileName;
69                 bool childrenAsProperties;
70                 bool isIParserAccessor = true;
71                 bool hasAspCode;
72                 ControlBuilder defaultPropertyBuilder;
73                 ArrayList children;
74                 ArrayList templateChildren;
75                 static int nextID;
76
77                 bool haveParserVariable;
78                 CodeMemberMethod method;
79                 CodeStatementCollection methodStatements;
80                 CodeMemberMethod renderMethod;
81                 int renderIndex;
82                 bool isProperty;
83                 ILocation location;
84                 ArrayList otherTags;
85                 
86                 public ControlBuilder ()
87                 {
88                 }
89
90                 internal ControlBuilder (TemplateParser parser,
91                                          ControlBuilder parentBuilder,
92                                          Type type,
93                                          string tagName,
94                                          string id,
95                                          IDictionary attribs,
96                                          int line,
97                                          string sourceFileName)
98
99                 {
100                         this.parser = parser;
101                         this.parserType = parser != null ? parser.GetType () : null;
102                         this.parentBuilder = parentBuilder;
103                         this.type = type;
104                         this.tagName = tagName;
105                         this.id = id;
106                         this.attribs = attribs;
107                         this.line = line;
108                         this.fileName = sourceFileName;
109                 }
110
111                 internal void EnsureOtherTags ()
112                 {
113                         if (otherTags == null)
114                                 otherTags = new ArrayList ();
115                 }
116
117                 internal ControlBuilder ParentBuilder {
118                         get { return parentBuilder; }
119                 }
120
121                 internal IDictionary Attributes {
122                         get { return attribs; }
123                 }
124
125                 internal int Line {
126                         get { return line; }
127                         set { line = value; }
128                 }
129
130                 internal string FileName {
131                         get { return fileName; }
132                         set { fileName = value; }
133                 }
134
135                 internal ControlBuilder DefaultPropertyBuilder {
136                         get { return defaultPropertyBuilder; }
137                 }
138
139                 internal bool HaveParserVariable {
140                         get { return haveParserVariable; }
141                         set { haveParserVariable = value; }
142                 }
143
144                 internal CodeMemberMethod Method {
145                         get { return method; }
146                         set { method = value; }
147                 }
148
149                 internal CodeMemberMethod DataBindingMethod {
150                         get;
151                         set;
152                 }
153                         
154                 internal CodeStatementCollection MethodStatements {
155                         get { return methodStatements; }
156                         set { methodStatements = value; }
157                 }
158
159                 internal CodeMemberMethod RenderMethod {
160                         get { return renderMethod; }
161                         set { renderMethod = value; }
162                 }
163
164                 internal int RenderIndex {
165                         get { return renderIndex; }
166                 }
167
168                 internal bool IsProperty {
169                         get { return isProperty; }
170                 }
171
172                 internal ILocation Location {
173                         get { return location; }
174                         set { location = new _Location (value); }
175                 }
176         
177                 internal ArrayList OtherTags {
178                         get { return otherTags; }
179                 }
180
181                 public Type ControlType {
182                         get { return type; }
183                 }
184
185                 protected bool FChildrenAsProperties {
186                         get { return childrenAsProperties; }
187                 }
188
189                 protected bool FIsNonParserAccessor {
190                         get { return !isIParserAccessor; }
191                 }
192
193                 public bool HasAspCode {
194                         get { return hasAspCode; }
195                 }
196
197                 public string ID {
198                         get { return id; }
199                         set { id = value; }
200                 }
201
202                 internal ArrayList Children {
203                         get { return children; }
204                 }
205
206                 internal ArrayList TemplateChildren {
207                         get { return templateChildren; }
208                 }
209                 
210                 internal void SetControlType (Type t)
211                 {
212                         type = t;
213                 }
214                 
215                 protected bool InDesigner {
216                         get { return false; }
217                 }
218
219                 public Type NamingContainerType {
220                         get {
221                                 ControlBuilder cb = myNamingContainer;
222                                 
223                                 if (cb == null)
224                                         return typeof (Control);
225
226                                 return cb.ControlType;
227                         }
228                 }
229
230                 internal bool IsNamingContainer {
231                         get {
232                                 if (type == null)
233                                         return false;
234
235                                 return typeof (INamingContainer).IsAssignableFrom (type);
236                         }
237                 }
238                 
239                 ControlBuilder MyNamingContainer {
240                         get {
241                                 if (myNamingContainer == null) {
242                                         Type controlType = parentBuilder != null ? parentBuilder.ControlType : null;
243                                         
244                                         if (parentBuilder == null && controlType == null)
245                                                 myNamingContainer = null;
246                                         else if (parentBuilder is TemplateBuilder)
247                                                 myNamingContainer = parentBuilder;
248                                         else if (controlType != null && typeof (INamingContainer).IsAssignableFrom (controlType))
249                                                 myNamingContainer = parentBuilder;
250                                         else
251                                                 myNamingContainer = parentBuilder.MyNamingContainer;
252                                 }
253
254                                 return myNamingContainer;
255                         }
256                 }
257                         
258                 public virtual Type BindingContainerType {
259                         get {
260                                 ControlBuilder cb = (this is TemplateBuilder && !(this is RootBuilder)) ? this : MyNamingContainer;
261                                 
262                                 if (cb == null) {
263                                         if (this is RootBuilder && parserType == typeof (PageParser)) 
264                                                 return typeof (Page);
265                                         
266                                         return typeof (Control);
267                                 }
268
269                                 if (cb != this && cb is ContentBuilderInternal && !typeof (INonBindingContainer).IsAssignableFrom (cb.BindingContainerType))
270                                         return cb.BindingContainerType;
271
272                                 Type ct;
273                                 if (cb is TemplateBuilder) {
274                                         ct = ((TemplateBuilder) cb).ContainerType;
275                                         if (typeof (INonBindingContainer).IsAssignableFrom (ct))
276                                                 return MyNamingContainer.BindingContainerType;
277                                         
278                                         if (ct != null)
279                                                 return ct;
280
281                                         ct = cb.ControlType;
282                                         if (ct == null)
283                                                 return typeof (Control);
284                                         
285                                         if (typeof (INonBindingContainer).IsAssignableFrom (ct) || !typeof (INamingContainer).IsAssignableFrom (ct))
286                                                 return MyNamingContainer.BindingContainerType;
287
288                                         return ct;
289                                 }
290
291                                 ct = cb.ControlType;
292                                 if (ct == null)
293                                         return typeof (Control);
294                                 
295                                 if (typeof (INonBindingContainer).IsAssignableFrom (ct) || !typeof (INamingContainer).IsAssignableFrom (ct))
296                                         return MyNamingContainer.BindingContainerType;
297                                 
298                                 return cb.ControlType;
299                         }
300                 }
301
302                 internal TemplateBuilder ParentTemplateBuilder {
303                         get {
304                                 if (parentBuilder == null)
305                                         return null;
306                                 else if (parentBuilder is TemplateBuilder)
307                                         return (TemplateBuilder) parentBuilder;
308                                 else
309                                         return parentBuilder.ParentTemplateBuilder;
310                         }
311                 }
312
313                 protected TemplateParser Parser {
314                         get { return parser; }
315                 }
316
317                 public string TagName {
318                         get { return tagName; }
319                 }
320
321                 internal string OriginalTagName {
322                         get {
323                                 if (originalTagName == null || originalTagName.Length == 0)
324                                         return TagName;
325                                 return originalTagName;
326                         }
327                 }
328                 
329                 internal RootBuilder Root {
330                         get {
331                                 if (typeof (RootBuilder).IsAssignableFrom (GetType ()))
332                                         return (RootBuilder) this;
333
334                                 return (RootBuilder) parentBuilder.Root;
335                         }
336                 }
337
338                 internal bool ChildrenAsProperties {
339                         get { return childrenAsProperties; }
340                 }
341
342                 internal string GetAttribute (string name)
343                 {
344                         if (attribs == null)
345                                 return null;
346
347                         return attribs [name] as string;
348                 }
349
350                 internal void IncreaseRenderIndex ()
351                 {
352                         renderIndex++;
353                 }
354                 
355                 void AddChild (object child)
356                 {
357                         if (children == null)
358                                 children = new ArrayList ();
359
360                         children.Add (child);
361                         ControlBuilder cb = child as ControlBuilder;
362                         if (cb != null && cb is TemplateBuilder) {
363                                 if (templateChildren == null)
364                                         templateChildren = new ArrayList ();
365                                 templateChildren.Add (child);
366                         }
367
368                         if (parser == null)
369                                 return;
370                         
371                         string tag = cb != null ? cb.TagName : null;
372                         if (String.IsNullOrEmpty (tag))
373                                 return;
374
375                         RootBuilder rb = Root;
376                         AspComponentFoundry foundry = rb != null ? rb.Foundry : null;
377                         if (foundry == null)
378                                 return;
379                         AspComponent component = foundry.GetComponent (tag);
380                         if (component == null || !component.FromConfig)
381                                 return;
382                         
383                         parser.AddImport (component.Namespace);
384                         parser.AddDependency (component.Source);
385                 }
386                 
387                 public virtual bool AllowWhitespaceLiterals ()
388                 {
389                         return true;
390                 }
391
392                 public virtual void AppendLiteralString (string s)
393                 {
394                         if (s == null || s.Length == 0)
395                                 return;
396
397                         if (childrenAsProperties || !isIParserAccessor) {
398                                 if (defaultPropertyBuilder != null) {
399                                         defaultPropertyBuilder.AppendLiteralString (s);
400                                 } else if (s.Trim ().Length != 0) {
401                                         throw new HttpException (String.Format ("Literal content not allowed for '{0}' {1} \"{2}\"",
402                                                                                 tagName, GetType (), s));
403                                 }
404
405                                 return;
406                         }
407                         
408                         if (!AllowWhitespaceLiterals () && s.Trim ().Length == 0)
409                                 return;
410
411                         if (HtmlDecodeLiterals ())
412                                 s = HttpUtility.HtmlDecode (s);
413
414                         AddChild (s);
415                 }
416
417                 public virtual void AppendSubBuilder (ControlBuilder subBuilder)
418                 {
419                         subBuilder.OnAppendToParentBuilder (this);
420                         
421                         subBuilder.parentBuilder = this;
422                         if (childrenAsProperties) {
423                                 AppendToProperty (subBuilder);
424                                 return;
425                         }
426
427                         if (typeof (CodeRenderBuilder).IsAssignableFrom (subBuilder.GetType ())) {
428                                 AppendCode (subBuilder);
429                                 return;
430                         }
431
432                         AddChild (subBuilder);
433                 }
434
435                 void AppendToProperty (ControlBuilder subBuilder)
436                 {
437                         if (typeof (CodeRenderBuilder) == subBuilder.GetType ())
438                                 throw new HttpException ("Code render not supported here.");
439
440                         if (defaultPropertyBuilder != null) {
441                                 defaultPropertyBuilder.AppendSubBuilder (subBuilder);
442                                 return;
443                         }
444
445                         AddChild (subBuilder);
446                 }
447
448                 void AppendCode (ControlBuilder subBuilder)
449                 {
450                         if (type != null && !(typeof (Control).IsAssignableFrom (type)))
451                                 throw new HttpException ("Code render not supported here.");
452
453                         if (typeof (CodeRenderBuilder) == subBuilder.GetType ())
454                                 hasAspCode = true;
455
456                         AddChild (subBuilder);
457                 }
458
459                 public virtual void CloseControl ()
460                 {
461                 }
462
463                 static Type MapTagType (Type tagType)
464                 {
465                         if (tagType == null)
466                                 return null;
467                         
468                         PagesSection ps = WebConfigurationManager.GetSection ("system.web/pages") as PagesSection;
469                         if (ps == null)
470                                 return tagType;
471
472                         TagMapCollection tags = ps.TagMapping;
473                         if (tags == null || tags.Count == 0)
474                                 return tagType;
475                         
476                         string tagTypeName = tagType.ToString ();
477                         Type mappedType, originalType;
478                         string originalTypeName = String.Empty, mappedTypeName = String.Empty;
479                         bool missingType;
480                         Exception error;
481                         
482                         foreach (TagMapInfo tmi in tags) {
483                                 error = null;
484                                 originalType = null;
485                                 
486                                 try {
487                                         originalTypeName = tmi.TagType;
488                                         originalType = HttpApplication.LoadType (originalTypeName);
489                                         if (originalType == null)
490                                                 missingType = true;
491                                         else
492                                                 missingType = false;
493                                 } catch (Exception ex) {
494                                         missingType = true;
495                                         error = ex;
496                                 }
497                                 if (missingType)
498                                         throw new HttpException (String.Format ("Could not load type {0}", originalTypeName), error);
499                                 
500                                 if (originalTypeName == tagTypeName) {
501                                         mappedTypeName = tmi.MappedTagType;
502                                         error = null;
503                                         mappedType = null;
504                                         
505                                         try {
506                                                 mappedType = HttpApplication.LoadType (mappedTypeName);
507                                                 if (mappedType == null)
508                                                         missingType = true;
509                                                 else
510                                                         missingType = false;
511                                         } catch (Exception ex) {
512                                                 missingType = true;
513                                                 error = ex;
514                                         }
515
516                                         if (missingType)
517                                                 throw new HttpException (String.Format ("Could not load type {0}", mappedTypeName),
518                                                                          error);
519                                         
520                                         if (!mappedType.IsSubclassOf (originalType))
521                                                 throw new ConfigurationErrorsException (
522                                                         String.Format ("The specified type '{0}' used for mapping must inherit from the original type '{1}'.", mappedTypeName, originalTypeName));
523
524                                         return mappedType;
525                                 }
526                         }
527                         
528                         return tagType;
529                 }
530
531                 public static ControlBuilder CreateBuilderFromType (TemplateParser parser,
532                                                                     ControlBuilder parentBuilder,
533                                                                     Type type,
534                                                                     string tagName,
535                                                                     string id,
536                                                                     IDictionary attribs,
537                                                                     int line,
538                                                                     string sourceFileName)
539                 {
540
541                         Type tagType = MapTagType (type);
542                         ControlBuilder builder;
543                         object [] atts = tagType.GetCustomAttributes (typeof (ControlBuilderAttribute), true);
544                         if (atts != null && atts.Length > 0) {
545                                 ControlBuilderAttribute att = (ControlBuilderAttribute) atts [0];
546                                 builder = (ControlBuilder) Activator.CreateInstance (att.BuilderType);
547                         } else {
548                                 builder = new ControlBuilder ();
549                         }
550
551                         builder.Init (parser, parentBuilder, tagType, tagName, id, attribs);
552                         builder.line = line;
553                         builder.fileName = sourceFileName;
554                         return builder;
555                 }
556
557                 public virtual Type GetChildControlType (string tagName, IDictionary attribs)
558                 {
559                         return null;
560                 }
561
562                 public virtual bool HasBody ()
563                 {
564                         return true;
565                 }
566
567                 public virtual bool HtmlDecodeLiterals ()
568                 {
569                         return false;
570                 }
571                 
572                 ControlBuilder CreatePropertyBuilder (string propName, TemplateParser parser, IDictionary atts)
573                 {
574                         int idx;
575                         string propertyName;
576                         
577                         if ((idx = propName.IndexOf (':')) >= 0)
578                                 propertyName = propName.Substring (idx + 1);
579                         else
580                                 propertyName = propName;
581                         
582                         PropertyInfo prop = type.GetProperty (propertyName, FlagsNoCase);
583                         if (prop == null) {
584                                 string msg = String.Format ("Property {0} not found in type {1}", propertyName, type);
585                                 throw new HttpException (msg);
586                         }
587
588                         Type propType = prop.PropertyType;
589                         ControlBuilder builder = null;
590                         if (typeof (ICollection).IsAssignableFrom (propType)) {
591                                 builder = new CollectionBuilder ();
592                         } else if (typeof (ITemplate).IsAssignableFrom (propType)) {
593                                 builder = new TemplateBuilder (prop);
594                         } else if (typeof (string) == propType) {
595                                 builder = new StringPropertyBuilder (prop.Name);
596                         } else {
597                                 builder = CreateBuilderFromType (parser, parentBuilder, propType, prop.Name,
598                                                                  null, atts, line, fileName);
599                                 builder.isProperty = true;
600                                 if (idx >= 0)
601                                         builder.originalTagName = propName;
602                                 return builder;
603                         }
604
605                         builder.Init (parser, this, null, prop.Name, null, atts);
606                         builder.fileName = fileName;
607                         builder.line = line;
608                         builder.isProperty = true;
609                         if (idx >= 0)
610                                 builder.originalTagName = propName;
611                         return builder;
612                 }
613                 
614                 public virtual void Init (TemplateParser parser,
615                                           ControlBuilder parentBuilder,
616                                           Type type,
617                                           string tagName,
618                                           string id,
619                                           IDictionary attribs)
620                 {
621                         this.parser = parser;
622                         if (parser != null)
623                                 this.Location = parser.Location;
624
625                         this.parentBuilder = parentBuilder;
626                         this.type = type;
627                         this.tagName = tagName;
628                         this.id = id;
629                         this.attribs = attribs;
630                         if (type == null)
631                                 return;
632
633                         if (this is TemplateBuilder)
634                                 return;
635
636                         object [] atts = type.GetCustomAttributes (typeof (ParseChildrenAttribute), true);
637                         
638                         if (!typeof (IParserAccessor).IsAssignableFrom (type) && atts.Length == 0) {
639                                 isIParserAccessor = false;
640                                 childrenAsProperties = true;
641                         } else if (atts.Length > 0) {
642                                 ParseChildrenAttribute att = (ParseChildrenAttribute) atts [0];
643                                 childrenAsProperties = att.ChildrenAsProperties;
644                                 if (childrenAsProperties && att.DefaultProperty.Length != 0)
645                                         defaultPropertyBuilder = CreatePropertyBuilder (att.DefaultProperty,
646                                                                                         parser, null);
647                         }
648                 }
649
650                 public virtual bool NeedsTagInnerText ()
651                 {
652                         return false;
653                 }
654
655                 public virtual void OnAppendToParentBuilder (ControlBuilder parentBuilder)
656                 {
657                         if (defaultPropertyBuilder == null)
658                                 return;
659
660                         ControlBuilder old = defaultPropertyBuilder;
661                         defaultPropertyBuilder = null;
662                         AppendSubBuilder (old);
663                 }
664
665                 internal void SetTagName (string name)
666                 {
667                         tagName = name;
668                 }
669                 
670                 public virtual void SetTagInnerText (string text)
671                 {
672                 }
673
674                 internal string GetNextID (string proposedID)
675                 {
676                         if (proposedID != null && proposedID.Trim ().Length != 0)
677                                 return proposedID;
678
679                         return "_bctrl_" + nextID++;
680                 }
681
682                 internal virtual ControlBuilder CreateSubBuilder (string tagid,
683                                                                   Hashtable atts,
684                                                                   Type childType,
685                                                                   TemplateParser parser,
686                                                                   ILocation location)
687                 {
688                         ControlBuilder childBuilder = null;
689                         if (childrenAsProperties) {
690                                 if (defaultPropertyBuilder == null)
691                                         childBuilder = CreatePropertyBuilder (tagid, parser, atts);
692                                 else {
693                                         if (String.Compare (defaultPropertyBuilder.TagName, tagid, true, Helpers.InvariantCulture) == 0) {
694                                                 // The child tag is the same what our default property name. Act as if there was
695                                                 // no default property builder, or otherwise we'll end up with invalid nested
696                                                 // builder call.
697                                                 defaultPropertyBuilder = null;
698                                                 childBuilder = CreatePropertyBuilder (tagid, parser, atts);
699                                         } else {
700                                                 Type ct = ControlType;
701                                                 MemberInfo[] mems = ct != null ? ct.GetMember (tagid, MemberTypes.Property, FlagsNoCase) : null;
702                                                 PropertyInfo prop = mems != null && mems.Length > 0 ? mems [0] as PropertyInfo : null;
703
704                                                 if (prop != null && typeof (ITemplate).IsAssignableFrom (prop.PropertyType)) {
705                                                         childBuilder = CreatePropertyBuilder (tagid, parser, atts);
706                                                         defaultPropertyBuilder = null;
707                                                 } else
708                                                         childBuilder = defaultPropertyBuilder.CreateSubBuilder (tagid, atts, null, parser, location);
709                                         }
710                                 }
711
712                                 return childBuilder;
713                         }
714
715                         if (String.Compare (tagName, tagid, true, Helpers.InvariantCulture) == 0)
716                                 return null;
717                         
718                         childType = GetChildControlType (tagid, atts);
719                         if (childType == null)
720                                 return null;
721
722                         childBuilder = CreateBuilderFromType (parser, this, childType, tagid, id, atts,
723                                                               location.BeginLine, location.Filename);
724
725                         return childBuilder;
726                 }
727
728                 internal virtual object CreateInstance ()
729                 {
730                         // HtmlGenericControl, HtmlTableCell...
731                         object [] atts = type.GetCustomAttributes (typeof (ConstructorNeedsTagAttribute), true);
732                         object [] args = null;
733                         if (atts != null && atts.Length > 0) {
734                                 ConstructorNeedsTagAttribute att = (ConstructorNeedsTagAttribute) atts [0];
735                                 if (att.NeedsTag)
736                                         args = new object [] {tagName};
737                         }
738
739                         return Activator.CreateInstance (type, args);
740                 }
741
742                 internal virtual void CreateChildren (object parent) 
743                 {
744                         if (children == null || children.Count == 0)
745                                 return;
746
747                         IParserAccessor parser = parent as IParserAccessor;
748                         if (parser == null)
749                                 return;
750
751                         foreach (object o in children) {
752                                 if (o is string) {
753                                         parser.AddParsedSubObject (new LiteralControl ((string) o));
754                                 } else {
755                                         parser.AddParsedSubObject (((ControlBuilder) o).CreateInstance ());
756                                 }
757                         }
758                 }
759
760                 [MonoTODO ("unsure, lack documentation")]
761                 public virtual object BuildObject ()
762                 {
763                         return CreateInstance ();
764                 }
765                 
766                 public virtual void ProcessGeneratedCode(CodeCompileUnit codeCompileUnit,
767                                                          CodeTypeDeclaration baseType,
768                                                          CodeTypeDeclaration derivedType,
769                                                          CodeMemberMethod buildMethod,
770                                                          CodeMemberMethod dataBindingMethod)
771                 {
772                         // nothing to do
773                 }
774
775                 internal void ResetState()
776                 {
777                         renderIndex = 0;
778                         haveParserVariable = false;
779
780                         if (Children != null) {
781                                 foreach (object child in Children) {
782                                         ControlBuilder cb = child as ControlBuilder;
783                                         if (cb != null)
784                                                 cb.ResetState ();
785                                 }
786                         }
787                 }
788         }
789 }