private GetAttributes ( object component, bool noCustomTypeDesc ) : |
||
component | object | |
noCustomTypeDesc | bool | |
return |
public static AttributeCollection GetAttributes(object component, bool noCustomTypeDesc)
{
if (component == null)
{
Debug.Fail("COMPAT: Returning an empty collection, but you should not pass null here");
return new AttributeCollection((Attribute[])null);
}
// We create a sort of pipeline for mucking with metadata. The pipeline
// goes through the following process:
//
// 1. Merge metadata from extenders.
// 2. Allow services to filter the metadata
// 3. If an attribute filter was specified, apply that.
//
// The goal here is speed. We get speed by not copying or
// allocating memory. We do this by allowing each phase of the
// pipeline to cache its data in the object cache. If
// a phase makes a change to the results, this change must cause
// successive phases to recompute their results as well. "Results" is
// always a collection, and the various stages of the pipeline may
// replace or modify this collection (depending on if it's a
// read-only IList or not). It is possible for the orignal
// descriptor or attribute collection to pass through the entire
// pipeline without modification.
//
ICustomTypeDescriptor typeDesc = GetDescriptor(component, noCustomTypeDesc);
ICollection results = typeDesc.GetAttributes();
// If we are handed a custom type descriptor we have several choices of action
// we can take. If noCustomTypeDesc is true, it means that the custom type
// descriptor is trying to find a baseline set of properties. In this case
// we should merge in extended properties, but we do not let designers filter
// because we're not done with the property set yet. If noCustomTypeDesc
// is false, we don't do extender properties because the custom type descriptor
// has already added them. In this case, we are doing a final pass so we
// want to apply filtering. Finally, if the incoming object is not a custom
// type descriptor, we do extenders and the filter.
//
if (component is ICustomTypeDescriptor)
{
if (noCustomTypeDesc)
{
ICustomTypeDescriptor extDesc = GetExtendedDescriptor(component);
if (extDesc != null)
{
ICollection extResults = extDesc.GetAttributes();
results = PipelineMerge(PIPELINE_ATTRIBUTES, results, extResults, component, null);
}
}
else
{
results = PipelineFilter(PIPELINE_ATTRIBUTES, results, component, null);
}
}
else
{
IDictionary cache = GetCache(component);
results = PipelineInitialize(PIPELINE_ATTRIBUTES, results, cache);
ICustomTypeDescriptor extDesc = GetExtendedDescriptor(component);
if (extDesc != null)
{
ICollection extResults = extDesc.GetAttributes();
results = PipelineMerge(PIPELINE_ATTRIBUTES, results, extResults, component, cache);
}
results = PipelineFilter(PIPELINE_ATTRIBUTES, results, component, cache);
}
AttributeCollection attrs = results as AttributeCollection;
if (attrs == null)
{
Attribute[] attrArray = new Attribute[results.Count];
results.CopyTo(attrArray, 0);
attrs = new AttributeCollection(attrArray);
}
return attrs;
}
TypeDescriptor::GetAttributes ( |
|
TypeDescriptor::GetAttributes ( object component ) : |
/// <summary> /// Retrieves custom attributes. /// </summary> internal AttributeCollection GetAttributes() { // Worst case collision scenario: we don't want the perf hit // of taking a lock, so if we collide we will query for // attributes twice. Not a big deal. if (_attributes == null) { // Obtaining attributes follows a very critical order: we must take care that // we merge attributes the right way. Consider this: // // [A4] // interface IBase; // // [A3] // interface IDerived; // // [A2] // class Base : IBase; // // [A1] // class Derived : Base, IDerived // // Calling GetAttributes on type Derived must merge attributes in the following // order: A1 - A4. Interfaces always lose to types, and interfaces and types // must be merged in the same order. At the same time, we must be careful // that we don't always go through reflection here, because someone could have // created a custom provider for a type. Because there is only one instance // of ReflectTypeDescriptionProvider created for typeof(object), if our code // is invoked here we can be sure that there is no custom provider for // _type all the way up the base class chain. // We cannot be sure that there is no custom provider for // interfaces that _type implements, however, because they are not derived // from _type. So, for interfaces, we must go through TypeDescriptor // again to get the interfaces attributes. // Get the type's attributes. This does not recurse up the base class chain. // We append base class attributes to this array so when walking we will // walk from Length - 1 to zero. // Attribute[] attrArray = ReflectGetAttributes(_type); Type baseType = _type.BaseType; while (baseType != null && baseType != typeof(object)) { Attribute[] baseArray = ReflectGetAttributes(baseType); Attribute[] temp = new Attribute[attrArray.Length + baseArray.Length]; Array.Copy(attrArray, temp, attrArray.Length); Array.Copy(baseArray, 0, temp, attrArray.Length, baseArray.Length); attrArray = temp; baseType = baseType.BaseType; } // Next, walk the type's interfaces. We append these to // the attribute array as well. int ifaceStartIdx = attrArray.Length; Type[] interfaces = _type.GetInterfaces(); for (int idx = 0; idx < interfaces.Length; idx++) { Type iface = interfaces[idx]; // Only do this for public interfaces. if ((iface.Attributes & (TypeAttributes.Public | TypeAttributes.NestedPublic)) != 0) { // No need to pass an instance into GetTypeDescriptor here because, if someone provided a custom // provider based on object, it already would have hit. AttributeCollection ifaceAttrs = TypeDescriptor.GetAttributes(iface); if (ifaceAttrs.Count > 0) { Attribute[] temp = new Attribute[attrArray.Length + ifaceAttrs.Count]; Array.Copy(attrArray, temp, attrArray.Length); ifaceAttrs.CopyTo(temp, attrArray.Length); attrArray = temp; } } } // Finally, put all these attributes in a dictionary and filter out the duplicates. OrderedDictionary attrDictionary = new OrderedDictionary(attrArray.Length); for (int idx = 0; idx < attrArray.Length; idx++) { bool addAttr = true; if (idx >= ifaceStartIdx) { for (int ifaceSkipIdx = 0; ifaceSkipIdx < s_skipInterfaceAttributeList.Length; ifaceSkipIdx++) { if (s_skipInterfaceAttributeList[ifaceSkipIdx].IsInstanceOfType(attrArray[idx])) { addAttr = false; break; } } } if (addAttr && !attrDictionary.Contains(attrArray[idx].TypeId)) { attrDictionary[attrArray[idx].TypeId] = attrArray[idx]; } } attrArray = new Attribute[attrDictionary.Count]; attrDictionary.Values.CopyTo(attrArray, 0); _attributes = new AttributeCollection(attrArray); } return(_attributes); }