AspElements.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907
  1. //
  2. // System.Web.Compilation.AspElements
  3. //
  4. // Authors:
  5. // Gonzalo Paniagua Javier ([email protected])
  6. //
  7. // (C) 2002 Ximian, Inc (http://www.ximian.com)
  8. //
  9. using System;
  10. using System.Collections;
  11. using System.IO;
  12. using System.Reflection;
  13. using System.Text;
  14. using System.Web.UI;
  15. using System.Web.UI.HtmlControls;
  16. using System.Web.UI.WebControls;
  17. using System.Web.Util;
  18. namespace System.Web.Compilation
  19. {
  20. enum ElementType
  21. {
  22. TAG,
  23. PLAINTEXT
  24. }
  25. abstract class Element
  26. {
  27. private ElementType elementType;
  28. public Element (ElementType type)
  29. {
  30. elementType = type;
  31. }
  32. public ElementType GetElementType
  33. {
  34. get { return elementType; }
  35. }
  36. } // class Element
  37. class PlainText : Element
  38. {
  39. private StringBuilder text;
  40. public PlainText () : base (ElementType.PLAINTEXT)
  41. {
  42. text = new StringBuilder ();
  43. }
  44. public PlainText (StringBuilder text) : base (ElementType.PLAINTEXT)
  45. {
  46. this.text = text;
  47. }
  48. public PlainText (string text) : this ()
  49. {
  50. this.text.Append (text);
  51. }
  52. public void Append (string more)
  53. {
  54. text.Append (more);
  55. }
  56. public string Text
  57. {
  58. get { return text.ToString (); }
  59. }
  60. public override string ToString ()
  61. {
  62. return "PlainText: " + Text;
  63. }
  64. }
  65. enum TagType
  66. {
  67. DIRECTIVE,
  68. HTML,
  69. HTMLCONTROL,
  70. SERVERCONTROL,
  71. INLINEVAR,
  72. INLINECODE,
  73. CLOSING,
  74. SERVEROBJECT,
  75. PROPERTYTAG,
  76. CODERENDER,
  77. DATABINDING,
  78. SERVERCOMMENT,
  79. NOTYET
  80. }
  81. /*
  82. * Attributes and values are stored in a couple of ArrayList in Add ().
  83. * When MakeHash () is called, they are converted to a Hashtable. If there are any
  84. * attributes duplicated it throws an ArgumentException.
  85. *
  86. * The [] operator works with the Hashtable if the values are in it, otherwise
  87. * it uses the ArrayList's.
  88. *
  89. * Why? You can have a tag in HTML like <a att="value" att="xxx">, but not in tags
  90. * marked runat=server and Hashtable requires the key to be unique.
  91. *
  92. */
  93. class TagAttributes
  94. {
  95. private Hashtable atts_hash;
  96. private ArrayList keys;
  97. private ArrayList values;
  98. private bool got_hashed;
  99. public TagAttributes ()
  100. {
  101. got_hashed = false;
  102. keys = new ArrayList ();
  103. values = new ArrayList ();
  104. }
  105. private void MakeHash ()
  106. {
  107. atts_hash = new Hashtable (CaseInsensitiveHashCodeProvider.Default,
  108. CaseInsensitiveComparer.Default);
  109. for (int i = 0; i < keys.Count; i++)
  110. atts_hash.Add (keys [i], values [i]);
  111. got_hashed = true;
  112. keys = null;
  113. values = null;
  114. }
  115. public bool IsRunAtServer ()
  116. {
  117. return got_hashed;
  118. }
  119. public void Add (object key, object value)
  120. {
  121. if (key != null && value != null &&
  122. 0 == String.Compare ((string) key, "runat", true) &&
  123. 0 == String.Compare ((string) value, "server", true))
  124. MakeHash ();
  125. if (got_hashed)
  126. atts_hash.Add (key, value);
  127. else {
  128. keys.Add (key);
  129. values.Add (value);
  130. }
  131. }
  132. public ICollection Keys
  133. {
  134. get { return (got_hashed ? atts_hash.Keys : keys); }
  135. }
  136. private int CaseInsensitiveSearch (string key)
  137. {
  138. // Hope not to have many attributes when the tag is not a server tag...
  139. for (int i = 0; i < keys.Count; i++){
  140. if (0 == String.Compare ((string) keys [i], key, true))
  141. return i;
  142. }
  143. return -1;
  144. }
  145. public object this [object key]
  146. {
  147. get {
  148. if (got_hashed)
  149. return atts_hash [key];
  150. int idx = CaseInsensitiveSearch ((string) key);
  151. if (idx == -1)
  152. return null;
  153. return values [idx];
  154. }
  155. set {
  156. if (got_hashed)
  157. atts_hash [key] = value;
  158. else {
  159. int idx = CaseInsensitiveSearch ((string) key);
  160. keys [idx] = value;
  161. }
  162. }
  163. }
  164. public int Count
  165. {
  166. get { return (got_hashed ? atts_hash.Count : keys.Count);}
  167. }
  168. public bool IsDataBound (string att)
  169. {
  170. if (att == null || !got_hashed)
  171. return false;
  172. return (att.StartsWith ("<%#") && att.EndsWith ("%>"));
  173. }
  174. public override string ToString ()
  175. {
  176. StringBuilder result = new StringBuilder ();
  177. string value;
  178. foreach (string key in Keys){
  179. result.Append (key);
  180. value = this [key] as string;
  181. if (value != null)
  182. result.AppendFormat ("=\"{0}\"", value);
  183. result.Append (' ');
  184. }
  185. if (result.Length > 0 && result [result.Length - 1] == ' ')
  186. result.Length--;
  187. return result.ToString ();
  188. }
  189. }
  190. class Tag : Element
  191. {
  192. protected string tag;
  193. protected TagType tagType;
  194. protected TagAttributes attributes;
  195. protected bool self_closing;
  196. protected bool hasDefaultID;
  197. private static int ctrlNumber = 1;
  198. ArrayList elements;
  199. internal Tag (ElementType etype) : base (etype) { }
  200. internal Tag (Tag other) :
  201. this (other.tag, other.attributes, other.self_closing)
  202. {
  203. this.tagType = other.tagType;
  204. }
  205. public Tag (string tag, TagAttributes attributes, bool self_closing) :
  206. base (ElementType.TAG)
  207. {
  208. if (tag == null)
  209. throw new ArgumentNullException ();
  210. this.tag = tag;
  211. this.attributes = attributes;
  212. this.tagType = TagType.NOTYET;
  213. this.self_closing = self_closing;
  214. this.hasDefaultID = false;
  215. }
  216. void ParseError (string msg, int line, int col)
  217. {
  218. string exc = String.Format ("error parsing attributes: {0}", msg);
  219. throw new HttpException (exc);
  220. }
  221. void TagParsed (Tag tag, int line, int col)
  222. {
  223. elements.Add (tag);
  224. }
  225. void TextParsed (string msg, int line, int col)
  226. {
  227. elements.Add (new PlainText (msg));
  228. }
  229. public ArrayList GetElements ()
  230. {
  231. string text = this.PlainHtml;
  232. string inner = text.Substring (1, text.Length - 2);
  233. byte [] bytes = WebEncoding.Encoding.GetBytes (inner);
  234. AspTokenizer tok = new AspTokenizer ("@@inner_string", new MemoryStream (bytes));
  235. AspParser parser = new AspParser (tok);
  236. elements = new ArrayList ();
  237. parser.Error += new ParseErrorHandler (ParseError);
  238. parser.TagParsed += new TagParsedHandler (TagParsed);
  239. parser.TextParsed += new TextParsedHandler (TextParsed);
  240. parser.Parse ();
  241. elements.Insert (0, new PlainText ("<"));
  242. elements.Add (new PlainText (">"));
  243. return elements;
  244. }
  245. public string TagID
  246. {
  247. get { return tag; }
  248. }
  249. public TagType TagType
  250. {
  251. get { return tagType; }
  252. }
  253. public bool SelfClosing
  254. {
  255. get { return self_closing; }
  256. }
  257. public TagAttributes Attributes
  258. {
  259. get { return attributes; }
  260. }
  261. public string PlainHtml
  262. {
  263. get {
  264. StringBuilder plain = new StringBuilder ();
  265. plain.Append ('<');
  266. if (tagType == TagType.CLOSING)
  267. plain.Append ('/');
  268. plain.Append (tag);
  269. if (attributes != null){
  270. plain.Append (' ');
  271. plain.Append (attributes.ToString ());
  272. }
  273. if (self_closing)
  274. plain.Append ('/');
  275. plain.Append ('>');
  276. return plain.ToString ();
  277. }
  278. }
  279. public override string ToString ()
  280. {
  281. return TagID + " " + Attributes + " " + self_closing;
  282. }
  283. public bool HasDefaultID
  284. {
  285. get { return hasDefaultID; }
  286. }
  287. protected virtual void SetNewID ()
  288. {
  289. if (attributes == null)
  290. attributes = new TagAttributes ();
  291. attributes.Add ("ID", GetDefaultID ());
  292. hasDefaultID = true;
  293. }
  294. public static string GetDefaultID ()
  295. {
  296. return "_control" + ctrlNumber++;
  297. }
  298. }
  299. class CloseTag : Tag
  300. {
  301. public CloseTag (string tag) : base (tag, null, false)
  302. {
  303. tagType = TagType.CLOSING;
  304. }
  305. }
  306. class Directive : Tag
  307. {
  308. // 'codebehind' is just ignored for Page, Application and Control
  309. private static Hashtable directivesHash;
  310. private static string [] page_atts = { "AspCompat", "AutoEventWireup", "Buffer",
  311. "ClassName", "ClientTarget", "CodePage",
  312. "CompilerOptions", "ContentType", "Culture", "Debug",
  313. "Description", "EnableSessionState", "EnableViewState",
  314. "EnableViewStateMac", "ErrorPage", "Explicit",
  315. "Inherits", "Language", "LCID", "ResponseEncoding",
  316. "Src", "SmartNavigation", "Strict", "Trace",
  317. "TraceMode", "Transaction", "UICulture",
  318. "WarningLevel", "CodeBehind" };
  319. private static string [] control_atts = { "AutoEventWireup", "ClassName", "CompilerOptions",
  320. "Debug", "Description", "EnableViewState",
  321. "Explicit", "Inherits", "Language", "Strict", "Src",
  322. "WarningLevel", "CodeBehind" };
  323. private static string [] import_atts = { "namespace" };
  324. private static string [] implements_atts = { "interface" };
  325. private static string [] assembly_atts = { "name", "src" };
  326. private static string [] register_atts = { "tagprefix", "tagname", "Namespace",
  327. "Src", "Assembly" };
  328. private static string [] outputcache_atts = { "Duration", "Location", "VaryByControl",
  329. "VaryByCustom", "VaryByHeader", "VaryByParam" };
  330. private static string [] reference_atts = { "page", "control" };
  331. private static string [] webservice_atts = { "class", "codebehind", "debug", "language" };
  332. private static string [] application_atts = { "description", "inherits", "codebehind" };
  333. static Directive ()
  334. {
  335. InitHash ();
  336. }
  337. private static void InitHash ()
  338. {
  339. CaseInsensitiveHashCodeProvider provider = new CaseInsensitiveHashCodeProvider ();
  340. CaseInsensitiveComparer comparer = new CaseInsensitiveComparer ();
  341. directivesHash = new Hashtable (provider, comparer);
  342. // Use Hashtable 'cause is O(1) in Contains (ArrayList is O(n))
  343. Hashtable valid_attributes = new Hashtable (provider, comparer);
  344. foreach (string att in page_atts) valid_attributes.Add (att, null);
  345. directivesHash.Add ("PAGE", valid_attributes);
  346. valid_attributes = new Hashtable (provider, comparer);
  347. foreach (string att in control_atts) valid_attributes.Add (att, null);
  348. directivesHash.Add ("CONTROL", valid_attributes);
  349. valid_attributes = new Hashtable (provider, comparer);
  350. foreach (string att in import_atts) valid_attributes.Add (att, null);
  351. directivesHash.Add ("IMPORT", valid_attributes);
  352. valid_attributes = new Hashtable (provider, comparer);
  353. foreach (string att in implements_atts) valid_attributes.Add (att, null);
  354. directivesHash.Add ("IMPLEMENTS", valid_attributes);
  355. valid_attributes = new Hashtable (provider, comparer);
  356. foreach (string att in register_atts) valid_attributes.Add (att, null);
  357. directivesHash.Add ("REGISTER", valid_attributes);
  358. valid_attributes = new Hashtable (provider, comparer);
  359. foreach (string att in assembly_atts) valid_attributes.Add (att, null);
  360. directivesHash.Add ("ASSEMBLY", valid_attributes);
  361. valid_attributes = new Hashtable (provider, comparer);
  362. foreach (string att in outputcache_atts) valid_attributes.Add (att, null);
  363. directivesHash.Add ("OUTPUTCACHE", valid_attributes);
  364. valid_attributes = new Hashtable (provider, comparer);
  365. foreach (string att in reference_atts) valid_attributes.Add (att, null);
  366. directivesHash.Add ("REFERENCE", valid_attributes);
  367. valid_attributes = new Hashtable (provider, comparer);
  368. foreach (string att in webservice_atts) valid_attributes.Add (att, null);
  369. directivesHash.Add ("WEBSERVICE", valid_attributes);
  370. valid_attributes = new Hashtable (provider, comparer);
  371. foreach (string att in application_atts) valid_attributes.Add (att, null);
  372. directivesHash.Add ("APPLICATION", valid_attributes);
  373. }
  374. public Directive (string tag, TagAttributes attributes) :
  375. base (tag, attributes, true)
  376. {
  377. CheckAttributes ();
  378. tagType = TagType.DIRECTIVE;
  379. }
  380. private void CheckAttributes ()
  381. {
  382. Hashtable atts;
  383. if (!(directivesHash [tag] is Hashtable))
  384. throw new ApplicationException ("Unknown directive: " + tag);
  385. if (attributes == null || attributes.Count == 0)
  386. return;
  387. atts = (Hashtable) directivesHash [tag];
  388. foreach (string att in attributes.Keys){
  389. if (!atts.Contains (att))
  390. throw new ApplicationException ("Attribute " + att +
  391. " not valid for tag " + tag);
  392. }
  393. }
  394. public static bool IsDirectiveID (string id)
  395. {
  396. return directivesHash.Contains (id);
  397. }
  398. public override string ToString ()
  399. {
  400. return "Directive: " + tag;
  401. }
  402. }
  403. class ServerObjectTag : Tag
  404. {
  405. public ServerObjectTag (Tag tag) :
  406. base (tag.TagID, tag.Attributes, tag.SelfClosing)
  407. {
  408. tagType = TagType.SERVEROBJECT;
  409. if (!attributes.IsRunAtServer ())
  410. throw new ApplicationException ("<object> without runat=server");
  411. if (attributes.Count != 3 || !SelfClosing || ObjectID == null || ObjectClass == null)
  412. throw new ApplicationException ("Incorrect syntax: <object id=\"name\" " +
  413. "class=\"full.class.name\" runat=\"server\" />");
  414. }
  415. public string ObjectID
  416. {
  417. get { return (string) attributes ["id"]; }
  418. }
  419. public string ObjectClass
  420. {
  421. get { return (string) attributes ["class"]; }
  422. }
  423. }
  424. class HtmlControlTag : Tag
  425. {
  426. private Type control_type;
  427. private bool is_container;
  428. private string parse_children;
  429. private bool got_parse_children;
  430. private static Hashtable controls;
  431. private static Hashtable inputTypes;
  432. private static void InitHash ()
  433. {
  434. controls = new Hashtable (new CaseInsensitiveHashCodeProvider (),
  435. new CaseInsensitiveComparer ());
  436. controls.Add ("A", typeof (HtmlAnchor));
  437. controls.Add ("BUTTON", typeof (HtmlButton));
  438. controls.Add ("FORM", typeof (HtmlForm));
  439. controls.Add ("IMG", typeof (HtmlImage));
  440. controls.Add ("INPUT", "INPUT");
  441. controls.Add ("SELECT", typeof (HtmlSelect));
  442. controls.Add ("TABLE", typeof (HtmlTable));
  443. controls.Add ("TD", typeof (HtmlTableCell));
  444. controls.Add ("TH", typeof (HtmlTableCell));
  445. controls.Add ("TR", typeof (HtmlTableRow));
  446. controls.Add ("TEXTAREA", typeof (HtmlTextArea));
  447. inputTypes = new Hashtable (new CaseInsensitiveHashCodeProvider (),
  448. new CaseInsensitiveComparer ());
  449. inputTypes.Add ("BUTTON", typeof (HtmlInputButton));
  450. inputTypes.Add ("SUBMIT", typeof (HtmlInputButton));
  451. inputTypes.Add ("RESET", typeof (HtmlInputButton));
  452. inputTypes.Add ("CHECKBOX", typeof (HtmlInputCheckBox));
  453. inputTypes.Add ("FILE", typeof (HtmlInputFile));
  454. inputTypes.Add ("HIDDEN", typeof (HtmlInputHidden));
  455. inputTypes.Add ("IMAGE", typeof (HtmlInputImage));
  456. inputTypes.Add ("RADIO", typeof (HtmlInputRadioButton));
  457. inputTypes.Add ("TEXT", typeof (HtmlInputText));
  458. inputTypes.Add ("PASSWORD", typeof (HtmlInputText));
  459. }
  460. static HtmlControlTag ()
  461. {
  462. InitHash ();
  463. }
  464. public HtmlControlTag (string tag, TagAttributes attributes, bool self_closing) :
  465. base (tag, attributes, self_closing)
  466. {
  467. SetData ();
  468. if (attributes == null || attributes ["ID"] == null)
  469. SetNewID ();
  470. }
  471. public HtmlControlTag (Tag source_tag) :
  472. this (source_tag.TagID, source_tag.Attributes, source_tag.SelfClosing)
  473. {
  474. }
  475. private void SetData ()
  476. {
  477. tagType = TagType.HTMLCONTROL;
  478. if (!(controls [tag] is string)){
  479. control_type = (Type) controls [tag];
  480. if (control_type == null)
  481. control_type = typeof (HtmlGenericControl);
  482. is_container = (0 != String.Compare (tag, "img", true));
  483. } else {
  484. string type_value = (string) attributes ["TYPE"];
  485. if (type_value== null)
  486. throw new ArgumentException ("INPUT tag without TYPE attribute!!!");
  487. control_type = (Type) inputTypes [type_value];
  488. //TODO: what does MS with this one?
  489. if (control_type == null)
  490. throw new ArgumentException ("Unknown input type -> " + type_value);
  491. is_container = false;
  492. self_closing = true; // All <input ...> are self-closing
  493. }
  494. }
  495. public Type ControlType
  496. {
  497. get { return control_type; }
  498. }
  499. public string ControlID
  500. {
  501. get { return (string) attributes ["ID"]; }
  502. }
  503. public bool IsContainer
  504. {
  505. get { return is_container; }
  506. }
  507. public string ParseChildren {
  508. get {
  509. if (got_parse_children)
  510. return parse_children;
  511. got_parse_children = true;
  512. object [] custom_atts = control_type.GetCustomAttributes (true);
  513. foreach (object att in custom_atts) {
  514. if (!(att is ParseChildrenAttribute))
  515. continue;
  516. ParseChildrenAttribute pc = (ParseChildrenAttribute) att;
  517. if (pc.ChildrenAsProperties == true)
  518. parse_children = pc.DefaultProperty;
  519. return parse_children;
  520. }
  521. return parse_children;
  522. }
  523. }
  524. public override string ToString ()
  525. {
  526. string ret = "HtmlControlTag: " + tag + " Name: " + ControlID + "Type:" +
  527. control_type.ToString () + "\n\tAttributes:\n";
  528. foreach (string key in attributes.Keys){
  529. ret += "\t" + key + "=" + attributes [key];
  530. }
  531. return ret;
  532. }
  533. }
  534. enum ChildrenKind
  535. {
  536. NONE,
  537. /*
  538. * Children must be ASP.NET server controls. Literal text is passed as LiteralControl.
  539. * Child controls and text are added using AddParsedSubObject ().
  540. */
  541. CONTROLS,
  542. /*
  543. * Children must correspond to properties of the parent control. No literal text allowed.
  544. */
  545. PROPERTIES,
  546. /*
  547. * Special case used inside <columns>...</columns>
  548. * Only allow DataGridColumn and derived classes.
  549. */
  550. DBCOLUMNS,
  551. /*
  552. * Special case for list controls (ListBox, DropDownList...)
  553. */
  554. LISTITEM,
  555. /* For HtmlSelect children. They are <option> tags that must
  556. * be treated as ListItem
  557. */
  558. OPTION,
  559. /* Childs of HtmlTable */
  560. HTMLROW,
  561. /* Childs of HtmlTableRow */
  562. HTMLCELL
  563. }
  564. // TODO: support for ControlBuilderAttribute that may be used in custom controls
  565. class AspComponent : Tag
  566. {
  567. private Type type;
  568. private string alias;
  569. private string control_type;
  570. private bool is_close_tag;
  571. private bool allow_children;
  572. private ChildrenKind children_kind;
  573. private string defaultPropertyName;
  574. private Type defaultPropertyType;
  575. ChildrenKind ChildrenKindFromProperty (Type type, string propertyName)
  576. {
  577. PropertyInfo prop = type.GetProperty (propertyName);
  578. if (prop == null)
  579. return ChildrenKind.LISTITEM;
  580. defaultPropertyType = prop.PropertyType;
  581. if (typeof (TableRowCollection).IsAssignableFrom (defaultPropertyType))
  582. return ChildrenKind.HTMLROW;
  583. if (typeof (TableCellCollection).IsAssignableFrom (defaultPropertyType))
  584. return ChildrenKind.HTMLCELL;
  585. return ChildrenKind.LISTITEM;
  586. }
  587. private ChildrenKind GuessChildrenKind (Type type)
  588. {
  589. object [] custom_atts = type.GetCustomAttributes (true);
  590. foreach (object custom_att in custom_atts){
  591. if (custom_att is ParseChildrenAttribute){
  592. /* FIXME
  593. * When adding full support for custom controls, we gotta
  594. * bear in mind the pca.DefaultProperty value
  595. */
  596. ParseChildrenAttribute pca = custom_att as ParseChildrenAttribute;
  597. defaultPropertyName = pca.DefaultProperty;
  598. /* this property will be true for all controls derived from
  599. * WebControls. */
  600. if (pca.ChildrenAsProperties == false)
  601. return ChildrenKind.CONTROLS;
  602. else if (defaultPropertyName == "")
  603. return ChildrenKind.PROPERTIES;
  604. else
  605. return ChildrenKindFromProperty (type, defaultPropertyName);
  606. }
  607. }
  608. return ChildrenKind.NONE;
  609. }
  610. private static bool GuessAllowChildren (Type type)
  611. {
  612. PropertyInfo controls = type.GetProperty ("Controls");
  613. if (controls == null)
  614. return false;
  615. MethodInfo getm = controls.GetGetMethod ();
  616. object control_instance = Activator.CreateInstance (type);
  617. object control_collection = getm.Invoke (control_instance, null);
  618. return (!(control_collection is System.Web.UI.EmptyControlCollection));
  619. }
  620. public AspComponent (Tag input_tag, Type type) :
  621. base (input_tag)
  622. {
  623. tagType = TagType.SERVERCONTROL;
  624. this.is_close_tag = input_tag is CloseTag;
  625. this.type = type;
  626. this.defaultPropertyName = "";
  627. this.allow_children = GuessAllowChildren (type);
  628. if (input_tag.SelfClosing)
  629. this.children_kind = ChildrenKind.NONE;
  630. else if (type == typeof (System.Web.UI.WebControls.DataGridColumn) ||
  631. type.IsSubclassOf (typeof (System.Web.UI.WebControls.DataGridColumn)))
  632. this.children_kind = ChildrenKind.PROPERTIES;
  633. else if (type == typeof (System.Web.UI.WebControls.ListItem))
  634. this.children_kind = ChildrenKind.CONTROLS;
  635. else
  636. this.children_kind = GuessChildrenKind (type);
  637. int pos = input_tag.TagID.IndexOf (':');
  638. alias = tag.Substring (0, pos);
  639. control_type = tag.Substring (pos + 1);
  640. if (attributes == null || attributes ["ID"] == null)
  641. SetNewID ();
  642. }
  643. public Type ComponentType
  644. {
  645. get { return type; }
  646. }
  647. public string ControlID
  648. {
  649. get { return (string) attributes ["ID"]; }
  650. }
  651. public bool IsCloseTag
  652. {
  653. get { return is_close_tag; }
  654. }
  655. public bool AllowChildren
  656. {
  657. get { return allow_children; }
  658. }
  659. public ChildrenKind ChildrenKind
  660. {
  661. get { return children_kind; }
  662. }
  663. public string DefaultPropertyName
  664. {
  665. get { return defaultPropertyName; }
  666. }
  667. public Type DefaultPropertyType
  668. {
  669. get { return defaultPropertyType; }
  670. }
  671. public override string ToString ()
  672. {
  673. return type.ToString () + " Alias: " + alias + " ID: " + (string) attributes ["id"];
  674. }
  675. }
  676. class PropertyTag : Tag
  677. {
  678. private Type type;
  679. private string name;
  680. public PropertyTag (Tag tag, Type type, string name)
  681. : base (tag)
  682. {
  683. tagType = TagType.PROPERTYTAG;
  684. SetNewID ();
  685. this.name = name;
  686. this.type = type;
  687. }
  688. public Type PropertyType
  689. {
  690. get { return type; }
  691. }
  692. public string PropertyID
  693. {
  694. get { return (string) attributes ["ID"]; }
  695. }
  696. public string PropertyName
  697. {
  698. get { return name; }
  699. }
  700. }
  701. class CodeRenderTag : Tag
  702. {
  703. private string code;
  704. private bool isVarName;
  705. public CodeRenderTag (bool isVarName, string code) : base ("", null, false)
  706. {
  707. tagType = TagType.CODERENDER;
  708. this.isVarName = isVarName;
  709. this.code = code.Trim ();
  710. }
  711. public string Code
  712. {
  713. get { return code; }
  714. }
  715. public bool IsVarName
  716. {
  717. get { return isVarName; }
  718. }
  719. public string AsText
  720. {
  721. get { return "<%" + (IsVarName ? "=" : "") + Code + "%>"; }
  722. }
  723. }
  724. class DataBindingTag : Tag
  725. {
  726. private string data;
  727. public DataBindingTag (string data) : base ("", null, false)
  728. {
  729. tagType = TagType.DATABINDING;
  730. this.data = data.Trim ();
  731. }
  732. public string Data
  733. {
  734. get { return data; }
  735. }
  736. public string AsText
  737. {
  738. get { return "<%#" + Data + "%>"; }
  739. }
  740. }
  741. class ServerComment : Tag
  742. {
  743. public ServerComment (string tag)
  744. : base (ElementType.TAG)
  745. {
  746. if (tag == null)
  747. throw new ArgumentNullException ();
  748. this.tag = tag;
  749. this.attributes = null;
  750. this.tagType = TagType.SERVERCOMMENT;
  751. this.self_closing = true;
  752. this.hasDefaultID = false;
  753. }
  754. public override string ToString ()
  755. {
  756. return TagID;
  757. }
  758. protected override void SetNewID ()
  759. {
  760. throw new NotSupportedException ();
  761. }
  762. }
  763. }