/*
         * 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");
		}
Beispiel #4
0
        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);
                }
            }
        }
Beispiel #5
0
        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);
        }
Beispiel #7
0
        /// <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);
        }
Beispiel #8
0
        /// <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 &lt;%@ Register %&gt; 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 &lt;%@ Register %&gt; 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));
                    }
                }
            }
        }