protected override void FillAttributes(IList attributes)
        {
            Debug.Assert(componentClass != null, "Must have a component class for FillAttributes");

            //
            // The order that we fill in attributes is critical.  The list of attributes will be
            // filtered so that matching attributes at the end of the list replace earlier matches
            // (last one in wins).  Therefore, the three categories of attributes we add must be
            // added as follows:
            //
            // 1.  Attributes of the property type.  These are the lowest level and should be
            //     overwritten by any newer attributes.
            //
            // 2.  Attributes of the property itself, from base class to most derived.  This way
            //     derived class attributes replace base class attributes.
            //
            // 3.  Attributes from our base MemberDescriptor.  While this seems opposite of what
            //     we want, MemberDescriptor only has attributes if someone passed in a new
            //     set in the constructor.  Therefore, these attributes always
            //     supercede existing values.
            //


            // We need to include attributes from the type of the property.
            //
            foreach (Attribute typeAttr in TypeDescriptor.GetAttributes(PropertyType))
            {
                attributes.Add(typeAttr);
            }

            // NOTE : Must look at method OR property, to handle the case of Extender properties...
            //
            // Note : Because we are using BindingFlags.DeclaredOnly it is more effcient to re-aquire
            //      : the property info, rather than use the one we have cached.  The one we have cached
            //      : may ave come from a base class, meaning we will request custom metadata for this
            //      : class twice.

            BindingFlags bindingFlags       = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.DeclaredOnly;
            Type         currentReflectType = componentClass;
            int          depth = 0;

            // First, calculate the depth of the object hierarchy.  We do this so we can do a single
            // object create for an array of attributes.
            //
            while (currentReflectType != null && currentReflectType != typeof(object))
            {
                depth++;
                currentReflectType = currentReflectType.BaseType;
            }

            // Now build up an array in reverse order
            //
            if (depth > 0)
            {
                currentReflectType = componentClass;
                object[][] attributeStack = new object[depth][];

                while (currentReflectType != null && currentReflectType != typeof(object))
                {
                    MemberInfo memberInfo = null;

                    // Fill in our member info so we can get at the custom attributes.
                    //
                    if (IsExtender)
                    {
                        memberInfo = currentReflectType.GetMethod("Get" + Name, bindingFlags);
                    }
                    else
                    {
                        memberInfo = currentReflectType.GetProperty(Name, bindingFlags, null, PropertyType, new Type[0], new ParameterModifier[0]);
                    }

                    // Get custom attributes for the member info.
                    //
                    if (memberInfo != null)
                    {
                        attributeStack[--depth] = TypeDescriptor.GetCustomAttributes(memberInfo);
                    }

                    // Ready for the next loop iteration.
                    //
                    currentReflectType = currentReflectType.BaseType;
                }

                // Now trawl the attribute stack so that we add attributes
                // from base class to most derived.
                //
                foreach (object[] attributeArray in attributeStack)
                {
                    if (attributeArray != null)
                    {
                        foreach (object attr in attributeArray)
                        {
                            if (attr is Attribute)
                            {
                                attributes.Add(attr);
                            }
                        }
                    }
                }
            }

            // Include the base attributes.  These override all attributes on the actual
            // property, so we want to add them last.
            //
            base.FillAttributes(attributes);

            // Finally, override any form of ReadOnlyAttribute.
            //
            if (!state[BitReadOnlyChecked])
            {
                state[BitReadOnlyChecked] = true;
                if (SetMethodValue == null)
                {
                    attributes.Add(ReadOnlyAttribute.Yes);
                }
            }
        }
        private void FillSingleMethodAttribute(MethodInfo realMethodInfo, IList attributes)
        {
            string       methodName         = realMethodInfo.Name;
            BindingFlags bindingFlags       = BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly;
            Type         currentReflectType = realMethodInfo.ReflectedType;

            Debug.Assert(currentReflectType != null, "currentReflectType cannot be null");

            // First, calculate the depth of the object hierarchy.  We do this so we can do a single
            // object create for an array of attributes.
            //
            int depth = 0;

            while (currentReflectType != null && currentReflectType != typeof(object))
            {
                depth++;
                currentReflectType = currentReflectType.BaseType;
            }

            if (depth > 0)
            {
                // Now build up an array in reverse order
                //
                currentReflectType = realMethodInfo.ReflectedType;
                object[][] attributeStack = new object[depth][];

                while (currentReflectType != null && currentReflectType != typeof(object))
                {
                    // Fill in our member info so we can get at the custom attributes.
                    //
                    MemberInfo memberInfo = currentReflectType.GetMethod(methodName, bindingFlags);

                    // Get custom attributes for the member info.
                    //
                    if (memberInfo != null)
                    {
                        attributeStack[--depth] = TypeDescriptor.GetCustomAttributes(memberInfo);
                    }

                    // Ready for the next loop iteration.
                    //
                    currentReflectType = currentReflectType.BaseType;
                }

                // Now trawl the attribute stack so that we add attributes
                // from base class to most derived.
                //
                foreach (object[] attributeArray in attributeStack)
                {
                    if (attributeArray != null)
                    {
                        foreach (object attr in attributeArray)
                        {
                            if (attr is Attribute)
                            {
                                attributes.Add(attr);
                            }
                        }
                    }
                }
            }
        }