/* * Initialize the builder * @param parser The instance of the parser that is controlling us. * @param tagName The name of the tag to be built. This is necessary * to allow a builder to support multiple tag types. * @param attribs IDictionary which holds all the attributes of * the tag. It is immutable. * @param type Type of the control that this builder will create. */ /// <include file='doc\ControlBuilder.uex' path='docs/doc[@for="BaseControlBuilder.Init"]/*' /> /// <devdoc> /// <para>[To be supplied.]</para> /// </devdoc> public virtual void Init(TemplateParser parser, ControlBuilder parentBuilder, Type type, string tagName, string id, IDictionary attribs) { _parser = parser; _parentBuilder = parentBuilder; _tagName = tagName; _id = id; _ctrlType = type; if (type != null) { // Try to get a ParseChildrenAttribute from the object ParseChildrenAttribute pca = null; object[] attrs = type.GetCustomAttributes(typeof(ParseChildrenAttribute), /*inherit*/ true); if ((attrs != null) && (attrs.Length == 1)) { Debug.Assert(attrs[0] is ParseChildrenAttribute); pca = (ParseChildrenAttribute)attrs[0]; } // Is this a builder for an object that implements IParserAccessor? if (!typeof(IParserAccessor).IsAssignableFrom(type)) { _fIsNonParserAccessor = true; // Non controls never have children _fChildrenAsProperties = true; } else { // Check if the nested tags define properties, as opposed to children if (pca != null) { _fChildrenAsProperties = pca.ChildrenAsProperties; } } if (_fChildrenAsProperties) { // Check if there is a default property if (pca != null && pca.DefaultProperty.Length != 0) { Type subType = null; // Create a builder for the default prop _defaultPropBuilder = CreateChildBuilder(pca.DefaultProperty, null /*attribs*/, parser, null, null /*id*/, _line, _sourceFileName, ref subType); Debug.Assert(_defaultPropBuilder != null, pca.DefaultProperty); } } } // Process the attributes, if any if (attribs != null) { PreprocessAttributes(attribs); } }
public void CtorBoolString_Deny_Unrestricted () { ParseChildrenAttribute pca = new ParseChildrenAttribute (true, "mono"); Assert.IsTrue (pca.ChildrenAsProperties, "ChildrenAsProperties"); Assert.AreEqual ("mono", pca.DefaultProperty, "DefaultProperty"); Assert.IsTrue (pca.Equals (pca), "Equals"); Assert.IsFalse (pca.IsDefaultAttribute (), "IsDefaultAttribute"); Assert.IsTrue (pca.GetHashCode () != 0, "GetHashCode"); // likely Assert.AreEqual (typeof (Control), pca.ChildControlType, "ChildControlType"); }
public void Ctor_Deny_Unrestricted () { ParseChildrenAttribute pca = new ParseChildrenAttribute (); Assert.IsFalse (pca.ChildrenAsProperties, "ChildrenAsProperties"); Assert.AreEqual (String.Empty, pca.DefaultProperty, "DefaultProperty"); Assert.IsTrue (pca.Equals (pca), "Equals"); Assert.IsTrue (pca.IsDefaultAttribute (), "IsDefaultAttribute"); // this throws a NullReferenceException on MS 2.0 beta2 // Assert.IsTrue (pca.GetHashCode () != 0, "GetHashCode"); // likely Assert.AreEqual (typeof (Control), pca.ChildControlType, "ChildControlType"); }
public virtual void Init(TemplateParser parser, ControlBuilder parentBuilder, Type type, string tagName, string id, IDictionary attribs) { this.parser = parser; if (parser != null) { this.Location = parser.Location; } this.parentBuilder = parentBuilder; this.type = type; this.tagName = tagName; this.id = id; this.attribs = attribs; if (type == null) { return; } if (this is TemplateBuilder) { return; } object [] atts = type.GetCustomAttributes(typeof(ParseChildrenAttribute), true); if (!typeof(IParserAccessor).IsAssignableFrom(type) && atts.Length == 0) { isIParserAccessor = false; childrenAsProperties = true; } else if (atts.Length > 0) { ParseChildrenAttribute att = (ParseChildrenAttribute)atts [0]; childrenAsProperties = att.ChildrenAsProperties; if (childrenAsProperties && att.DefaultProperty.Length != 0) { defaultPropertyBuilder = CreatePropertyBuilder(att.DefaultProperty, parser, null); } } }
public override bool Equals(object obj) { if (obj == this) { return(true); } ParseChildrenAttribute attribute = obj as ParseChildrenAttribute; if (attribute == null) { return(false); } if (!this._childrenAsProps) { return(!attribute.ChildrenAsProperties && (attribute._childControlType == this._childControlType)); } return(attribute.ChildrenAsProperties && this.DefaultProperty.Equals(attribute.DefaultProperty)); }
public override bool Equals(object obj) { ParseChildrenAttribute o = (obj as ParseChildrenAttribute); if (o == null) { return(false); } if (childrenAsProperties == o.childrenAsProperties) { if (childrenAsProperties == false) { return(true); } return(defaultProperty == o.DefaultProperty); } return(false); }
/// <include file='doc\ParseChildrenAsPropertiesAttribute.uex' path='docs/doc[@for="ParseChildrenAttribute.Equals"]/*' /> /// <devdoc> /// </devdoc> /// <internalonly/> public override bool Equals(object obj) { if (obj == this) { return(true); } ParseChildrenAttribute pca = obj as ParseChildrenAttribute; if (pca != null) { if (_childrenAsProps == false) { return(pca.ChildrenAsProperties == false); } else { return(pca.ChildrenAsProperties && (DefaultProperty.Equals(pca.DefaultProperty))); } } return(false); }
/// <summary> /// Construct a new blob of metadata for a single control, performing any reflection needed to determine its /// structure and parsing behavior. /// </summary> /// <param name="compileContext">The context in which errors should be reported.</param> /// <param name="tag">The complete tag for this control, as found in the markup.</param> /// <param name="tagRegistrations">The known list of registrations, formed from the directives in the /// "web.config" and any <%@ Register %> directives in the markup.</param> /// <param name="assemblies">The complete list of known pre-loaded assemblies for reflection.</param> /// <param name="allowedTypes">The allowable types of control that may be returned. If the matching /// .NET class type for this control does not match one of these types (or is not derivable from one /// of these types), this constructor will throw an exception.</param> public ReflectedControl(ICompileContext compileContext, Tag tag, IEnumerable <TagRegistration> tagRegistrations, AssemblyLoader assemblies, IEnumerable <Type> allowedTypes) { // Decode the tag declaration. DecodeFullTagNameWithPrefix(tag.TagName, out TagPrefix, out TagName); // Find the matching C# type for that tag declaration. if (string.IsNullOrEmpty(TagPrefix)) { TagRegistration = _htmlTagRegistration; ControlType = FindMatchingHtmlControlType(tag); } else { ControlType = FindMatchingControlType(TagPrefix, TagName, tagRegistrations, assemblies, out TagRegistration); } if (ControlType == null) { throw new InvalidOperationException(string.Format("No matching type for <{0}> was found in any of the loaded assemblies.", tag.TagName)); } // If we are restricted to only load certain types (such as the nested not-a-control instances inside a DataPager control), // check that the control we have found matches one of those types. if (!allowedTypes.Any(t => t.IsAssignableFrom(ControlType))) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendFormat("Found matching type for <{0}>, but it is a {1}, not one of the {2} allowed types:\r\n", tag.TagName, ControlType.FullName, allowedTypes.Count()); foreach (Type allowedType in allowedTypes) { stringBuilder.AppendFormat("- {0}\r\n", allowedType.FullName); } throw new InvalidOperationException(stringBuilder.ToString()); } // Extract the [ParseChildren] attribute, if it has one. System.Web.UI.ParseChildrenAttribute[] parseChildrenAttributes = (System.Web.UI.ParseChildrenAttribute[])ControlType.GetCustomAttributes(typeof(System.Web.UI.ParseChildrenAttribute), true); ParseChildrenAttribute = parseChildrenAttributes.Length == 0 ? null : parseChildrenAttributes[0]; // Extract the [ControlBuilder] attribute, if it has one. System.Web.UI.ControlBuilderAttribute[] controlBuilderAttributes = (System.Web.UI.ControlBuilderAttribute[])ControlType.GetCustomAttributes(typeof(System.Web.UI.ControlBuilderAttribute), true); ControlBuilderAttribute = controlBuilderAttributes.Length == 0 ? null : controlBuilderAttributes[0]; // Extract the type's properties, since their declarations control what's legal in the markup. ControlProperties = CollectControlProperties(compileContext, ControlType, this); // HtmlControls have to be handled specially, since they have [ParseChildren(true)] in many cases but // aren't really using it for anything. if (ControlType.Namespace == _htmlTagRegistration.Namespace) { ParseChildrenAttribute = new ParseChildrenAttribute(false); } // Validate the ParseChildrenAttribute, which may be broken or weird. if (ParseChildrenAttribute != null) { if (!string.IsNullOrEmpty(ParseChildrenAttribute.DefaultProperty)) { string propertyName = ParseChildrenAttribute.DefaultProperty.ToLower(); // ASP.NET also ignores case on this; see internals of ControlBuilder.CreateChildBuilder() for details. if (!ControlProperties.ContainsKey(propertyName)) { throw new InvalidOperationException(string.Format("The [ParseChildren] attribute on class \"{0}\" names a default property \"{1}\" that does not exist in that class.", ControlType.FullName, ParseChildrenAttribute.DefaultProperty)); } DefaultCollectionProperty = ControlProperties[propertyName]; if (!DefaultCollectionProperty.IsCollectionProperty) { throw new InvalidOperationException(string.Format("The [ParseChildren] attribute on class \"{0}\" names a default property \"{1}\" that is not a collection property. The default property must always be a collection property.", ControlType.FullName, ParseChildrenAttribute.DefaultProperty)); } } } }
public ServerObjectParsingObject(Type type, Hashtable attributes, string tagid, ParsingObject parent) : base (tagid, parent) { //create the object if (type.GetInterface ("System.ComponentModel.IComponent") != null) //note: this automatically adds to parent's container, as some controls //need to be sited e.g. if they use site dictionaries //TODO: should this action be passed up the tree so controls can intercept? obj = ((AspNetEdit.Editor.ComponentModel.DesignerHost) base.DesignerHost).CreateComponent (type, attributes["ID"] as string, false); else obj = Activator.CreateInstance (type); //and populate it from the attributes pdc = TypeDescriptor.GetProperties (obj); foreach (DictionaryEntry de in attributes) { if (0 == string.Compare((string)de.Key, "runat")) continue; if (0 == string.Compare((string)de.Key, "ID")) continue; //use the dash subproperty syntax string[] str = ((string)de.Key).Split ('-'); PropertyDescriptor pd = pdc.Find (str[0], true); //if property not found, try events if (str.Length == 1 && pd == null && CultureInfo.InvariantCulture.CompareInfo.IsPrefix (str[0].ToLower(), "on")) { IEventBindingService iebs = (IEventBindingService) DesignerHost.GetService (typeof (IEventBindingService)); if (iebs == null) throw new Exception ("Could not obtain IEventBindingService from host"); EventDescriptorCollection edc = TypeDescriptor.GetEvents (obj); EventDescriptor e = edc.Find (str[0].Remove(0,2), true); if (e != null) pd = iebs.GetEventProperty(e); else throw new Exception ("Could not find event " + str[0].Remove(0,2)); } object loopObj = obj; for (int i = 0; i < str.Length; i++ ) { if (pd == null) throw new Exception ("Could not find property " + (string)de.Key); if (i == str.Length - 1) { pd.SetValue (obj, pd.Converter.ConvertFromString ((string) de.Value)); break; } loopObj = pd.GetValue (loopObj); pd = TypeDescriptor.GetProperties (loopObj).Find (str[0], true); } } parseAtt = TypeDescriptor.GetAttributes (obj)[typeof(ParseChildrenAttribute )] as ParseChildrenAttribute; //FIXME: fix this in MCS classlib if (parseAtt.DefaultProperty.Length == 0) parseAtt = null; //work out how we're trying to parse the children if (parseAtt != null) { if (parseAtt.DefaultProperty != null) { PropertyDescriptor pd = pdc[parseAtt.DefaultProperty]; if (pd == null) throw new Exception ("Default property does not exist"); if (pd.PropertyType.GetInterface("System.Collections.IList") == (typeof(IList))) mode = ParseChildrenMode.DefaultCollectionProperty; else mode = ParseChildrenMode.DefaultProperty; } else if (parseAtt.ChildrenAsProperties) mode = ParseChildrenMode.Properties; else mode = ParseChildrenMode.Controls; } else { //FIXME: these are actually persistence hints, but ParseChildrenAttribute doesn't always exist. //FIXME: logic would be dodgy with bad input parseAtt = ParseChildrenAttribute.Default; mode = ParseChildrenMode.Controls; foreach (PropertyDescriptor pd in pdc) { PersistenceModeAttribute modeAttrib = pd.Attributes[typeof(PersistenceModeAttribute)] as PersistenceModeAttribute; if (modeAttrib == null) return; switch (modeAttrib.Mode) { case PersistenceMode.Attribute: continue; case PersistenceMode.EncodedInnerDefaultProperty: parseAtt.DefaultProperty = pd.Name; mode = ParseChildrenMode.DefaultEncodedProperty; break; case PersistenceMode.InnerDefaultProperty: parseAtt.DefaultProperty = pd.Name; if (pd.PropertyType.GetInterface("System.Collections.IList") == (typeof(IList))) mode = ParseChildrenMode.DefaultCollectionProperty; else mode = ParseChildrenMode.DefaultProperty; break; case PersistenceMode.InnerProperty: mode = ParseChildrenMode.Properties; break; } } } }
/// <summary> /// Construct a new blob of metadata for a single control, performing any reflection needed to determine its /// structure and parsing behavior. /// </summary> /// <param name="compileContext">The context in which errors should be reported.</param> /// <param name="tag">The complete tag for this control, as found in the markup.</param> /// <param name="tagRegistrations">The known list of registrations, formed from the directives in the /// "web.config" and any <%@ Register %> directives in the markup.</param> /// <param name="assemblies">The complete list of known pre-loaded assemblies for reflection.</param> /// <param name="allowedTypes">The allowable types of control that may be returned. If the matching /// .NET class type for this control does not match one of these types (or is not derivable from one /// of these types), this constructor will throw an exception.</param> public ReflectedControl(ICompileContext compileContext, Tag tag, IEnumerable <TagRegistration> tagRegistrations, ReferencedAssembliesContext assemblies, IEnumerable <Type> allowedTypes) { // Decode the tag declaration. DecodeFullTagNameWithPrefix(tag.TagName, out TagPrefix, out TagName); // Find the matching C# type for that tag declaration. if (string.IsNullOrEmpty(TagPrefix)) { TagRegistration = GetHtmlTagRegistration(assemblies.SystemWebAssembly); ControlType = FindMatchingHtmlControlType(tag, assemblies); } else { ControlType = FindMatchingControlType(TagPrefix, TagName, tagRegistrations, assemblies, out TagRegistration); } if (ControlType == null) { throw new InvalidOperationException(string.Format("No matching type for <{0}> was found in any of the loaded assemblies.", tag.TagName)); } // If we are restricted to only load certain types (such as the nested not-a-control instances inside a DataPager control), // check that the control we have found matches one of those types. var enumerable = allowedTypes as Type[] ?? allowedTypes.ToArray(); if (!enumerable.Any(t => IsSameOrSubclass(t, ControlType))) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendFormat("Found matching type for <{0}>, but it is a {1}, not one of the {2} allowed types:\r\n", tag.TagName, ControlType.FullName, enumerable.Count()); foreach (Type allowedType in enumerable) { stringBuilder.AppendFormat("- {0}\r\n", allowedType.FullName); } throw new InvalidOperationException(stringBuilder.ToString()); } // Extract the [ParseChildren] attribute, if it has one. var custAtts = CustomAttributeData.GetCustomAttributes(ControlType).Where(a => a.AttributeType == typeof(System.Web.UI.ParseChildrenAttribute)); if (custAtts.Any()) { var parseAtt = custAtts.First(); if (!parseAtt.ConstructorArguments.Any()) { ParseChildrenAttribute = new ParseChildrenAttribute(); //public ParseChildrenAttribute(); } else if (parseAtt.ConstructorArguments.Count == 1) { //public ParseChildrenAttribute(bool childrenAsProperties); //public ParseChildrenAttribute(Type childControlType); if (parseAtt.ConstructorArguments[0].ArgumentType == typeof(bool)) { bool val = (bool)parseAtt.ConstructorArguments[0].Value; ParseChildrenAttribute = new ParseChildrenAttribute(val); } else if (parseAtt.ConstructorArguments[0].ArgumentType == typeof(Type)) { Type val = (Type)parseAtt.ConstructorArguments[0].Value; ParseChildrenAttribute = new ParseChildrenAttribute(val); } } else { //public ParseChildrenAttribute(bool childrenAsProperties, string defaultProperty); bool val = (bool)parseAtt.ConstructorArguments[0].Value; String defaultPropVal = (string)parseAtt.ConstructorArguments[1].Value; ParseChildrenAttribute = new ParseChildrenAttribute(val, defaultPropVal); } } //System.Web.UI.ParseChildrenAttribute[] parseChildrenAttributes = (System.Web.UI.ParseChildrenAttribute[])ControlType.GetCustomAttributes(typeof(System.Web.UI.ParseChildrenAttribute), true); //ParseChildrenAttribute = parseChildrenAttributes.Length == 0 ? null : parseChildrenAttributes[0]; // Extract the [ControlBuilder] attribute, if it has one. var controlBuilderAttsData = CustomAttributeData.GetCustomAttributes(ControlType).Where(a => a.AttributeType == typeof(System.Web.UI.ControlBuilderAttribute)); if (controlBuilderAttsData.Any()) { var controlBuilderAttData = custAtts.First(); if (controlBuilderAttData.ConstructorArguments.Count() == 1) { Type val = (Type)controlBuilderAttData.ConstructorArguments[0].Value; ControlBuilderAttribute = new System.Web.UI.ControlBuilderAttribute(val); } } //System.Web.UI.ControlBuilderAttribute[] controlBuilderAttributes = (System.Web.UI.ControlBuilderAttribute[])ControlType.GetCustomAttributes(typeof(System.Web.UI.ControlBuilderAttribute), true); //ControlBuilderAttribute = controlBuilderAttributes.Length == 0 ? null : controlBuilderAttributes[0]; // Extract the type's properties, since their declarations control what's legal in the markup. ControlProperties = CollectControlProperties(compileContext, ControlType, this); // HtmlControls have to be handled specially, since they have [ParseChildren(true)] in many cases but // aren't really using it for anything. if (ControlType.Namespace == GetHtmlTagRegistration(assemblies.SystemWebAssembly).Namespace) { ParseChildrenAttribute = new ParseChildrenAttribute(false); } // Validate the ParseChildrenAttribute, which may be broken or weird. if (ParseChildrenAttribute != null) { if (!string.IsNullOrEmpty(ParseChildrenAttribute.DefaultProperty)) { string propertyName = ParseChildrenAttribute.DefaultProperty.ToLower(); // ASP.NET also ignores case on this; see internals of ControlBuilder.CreateChildBuilder() for details. if (!ControlProperties.ContainsKey(propertyName)) { throw new InvalidOperationException(string.Format("The [ParseChildren] attribute on class \"{0}\" names a default property \"{1}\" that does not exist in that class.", ControlType.FullName, ParseChildrenAttribute.DefaultProperty)); } DefaultCollectionProperty = ControlProperties[propertyName]; if (!DefaultCollectionProperty.IsCollectionProperty) { throw new InvalidOperationException(string.Format("The [ParseChildren] attribute on class \"{0}\" names a default property \"{1}\" that is not a collection property. The default property must always be a collection property.", ControlType.FullName, ParseChildrenAttribute.DefaultProperty)); } } } }