System.ComponentModel.ReflectPropertyDescriptor.FillAttributes C# (CSharp) Method

FillAttributes() protected method

protected FillAttributes ( IList attributes ) : void
attributes IList
return void
        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 four 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 obtained from any SpecificTypeAttribute.  These supercede attributes
            //     for the property type.
            //
            // 3.  Attributes of the property itself, from base class to most derived.  This way
            //     derived class attributes replace base class attributes.
            //
            // 4.  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.

            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.GetTypeInfo().BaseType;
            }

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

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

#if VERIFY_REFLECTION_CHANGE
                    BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.DeclaredOnly;
                    // Fill in our member info so we can get at the custom attributes.
                    //
                    if (IsExtender)
                    {
                        //receiverType is used to avoid ambitiousness when there are overloads for the get method.
                        memberInfo = currentReflectType.GetMethod("Get" + Name, bindingFlags, null, new Type[] { _receiverType }, null);
                    }
                    else
                    {
                        memberInfo = currentReflectType.GetProperty(Name, bindingFlags, null, PropertyType, Array.Empty<Type>(), Array.Empty<ParameterModifier>());
                    }
#else
                    // Fill in our member info so we can get at the custom attributes.
                    //
                    if (IsExtender)
                    {
                        //receiverType is used to avoid ambitiousness when there are overloads for the get method.
                        memberInfo = currentReflectType.GetTypeInfo().GetMethod("Get" + Name, new Type[] { _receiverType }, null);
                    }
                    else
                    {
                        memberInfo = currentReflectType.GetTypeInfo().GetProperty(Name, PropertyType, Array.Empty<Type>(), Array.Empty<ParameterModifier>());
                    }
#endif
                    // Get custom attributes for the member info.
                    //
                    if (memberInfo != null)
                    {
                        attributeStack[--depth] = ReflectTypeDescriptionProvider.ReflectGetAttributes(memberInfo);
                    }

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

                // Look in the attribute stack for AttributeProviders
                // 
                foreach (Attribute[] attributeArray in attributeStack)
                {
                    if (attributeArray != null)
                    {
                        foreach (Attribute attr in attributeArray)
                        {
                            AttributeProviderAttribute sta = attr as AttributeProviderAttribute;
                            if (sta != null)
                            {
                                Type specificType = Type.GetType(sta.TypeName);

                                if (specificType != null)
                                {
                                    Attribute[] stAttrs = null;

                                    if (!String.IsNullOrEmpty(sta.PropertyName))
                                    {
                                        MemberInfo[] milist = specificType.GetTypeInfo().GetMember(sta.PropertyName);
                                        if (milist.Length > 0 && milist[0] != null)
                                        {
                                            stAttrs = ReflectTypeDescriptionProvider.ReflectGetAttributes(milist[0]);
                                        }
                                    }
                                    else
                                    {
                                        stAttrs = ReflectTypeDescriptionProvider.ReflectGetAttributes(specificType);
                                    }
                                    if (stAttrs != null)
                                    {
                                        foreach (Attribute stAttr in stAttrs)
                                        {
                                            attributes.Add(stAttr);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                // Now trawl the attribute stack so that we add attributes
                // from base class to most derived.
                //
                foreach (Attribute[] attributeArray in attributeStack)
                {
                    if (attributeArray != null)
                    {
                        foreach (Attribute attr in attributeArray)
                        {
                            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 (SetMethodValue == null)
            {
                attributes.Add(ReadOnlyAttribute.Yes);
            }
        }