PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes) { // Rather than passing this function on to the default TypeDescriptor, // which would return the actual properties of PropertyBag, I construct // a list here that contains property descriptors for the elements of the // Properties list in the bag. ArrayList props = new ArrayList(); foreach (PropertySpec property in properties) { ArrayList attrs = new ArrayList(); // If a category, description, editor, or type converter are specified // in the PropertySpec, create attributes to define that relationship. if (property.Category != null) { attrs.Add(new CategoryAttribute(property.Category)); } if (property.Description != null) { attrs.Add(new DescriptionAttribute(property.Description)); } if (property.EditorTypeName != null) { attrs.Add(new EditorAttribute(property.EditorTypeName, typeof(UITypeEditor))); } if (property.ConverterTypeName != null) { attrs.Add(new TypeConverterAttribute(property.ConverterTypeName)); } // Additionally, append the custom attributes associated with the // PropertySpec, if any. if (property.Attributes != null) { attrs.AddRange(property.Attributes); } Attribute[] attrArray = (Attribute[])attrs.ToArray(typeof(Attribute)); // Create a new property descriptor for the property item, and add // it to the list. PropertySpecDescriptor pd = new PropertySpecDescriptor(property, this, property.Name, attrArray); props.Add(pd); } // Convert the list of PropertyDescriptors to a collection that the // ICustomTypeDescriptor can use, and return it. PropertyDescriptor[] propArray = (PropertyDescriptor[])props.ToArray( typeof(PropertyDescriptor)); return(new PropertyDescriptorCollection(propArray)); }