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); } } } } } }