// does some consisitency check between the CA list and every CA attribute usage and after // discarding unwanted CA return an array of them static private Object[] CheckConsistencyAndCreateArray(CustomAttribute caItem, Type caType) { // we got the max number of attributes, we may have to trim this list but let's get a count for now if (caItem == null) { return((caType == null || caType.IsValueType) ? s_gObjectEmptyArray : (Object[])Array.CreateInstance(caType, 0)); } int caCount = 0; int hasInherited = (caItem == null) ? 0 : caItem.m_inheritLevel; CustomAttribute caNext = caItem; CustomAttribute caPrev = null; // walk and revert the list while (caNext != null) { caCount++; CustomAttribute caTemp = caNext.m_next; caNext.m_next = caPrev; caPrev = caNext; caNext = caTemp; } caItem = caPrev; // now we have a list of custom attribute of some type. That list may contain subtype of the specific // type, so for every other type we have to go and check whether multiple and inherited are respected if (caCount > 0 && hasInherited > 0) { // keep track of the CA types so we can make inspection reasonable fast Hashtable htCAData = new Hashtable(11); // loop through the list of attributes checking for consistency, once an attribute // has been inspected is never going to be looked at again, and neither an attribute // of the same type. // This loop and the inspectedCATypes array should make that happen caNext = caItem; CustomAttribute caLast = null; while (caNext != null) { AttributeUsageAttribute usage = null; int caTypeLevelFound = 0; // get current attribute type Type t = caNext.GetAttributeType(); // look if the type has already been seen CAData caData = (CAData)htCAData[t]; if (caData != null) { usage = caData.usage; caTypeLevelFound = caData.level; } if (usage == null) { // no type found, load the attribute usage // do not save the attribute usage yet because the next block may discard // the attribute which implies we pretend we never saw. That is kind of // bad because we may end up reloading it again if another type comes into the picture // but we prefer the perf hit to more code complication for a case that seem to // be submarginal usage = CustomAttribute.GetAttributeUsage(t); } // if this is an inherited attribute and the attribute usage does not allow that, OR // if the attribute was seen already on a different inheritance level and multiple is not allowed // THEN discard if ((caNext.m_inheritLevel > 0 && !usage.Inherited) || (caData != null && caTypeLevelFound < caNext.m_inheritLevel && !usage.AllowMultiple)) { if (caLast == null) { caItem = caNext.m_next; } else { caLast.m_next = caNext.m_next; } caNext = caNext.m_next; caCount--; continue; } if (caData == null) { // the attribute was never seen so far so we should add it to the table and keep going htCAData[t] = new CAData(t, usage, caNext.m_inheritLevel); } caLast = caNext; caNext = caNext.m_next; } } // time to return the array if (caCount > 0) { if (caType == null || caType.IsValueType) { caType = s_ObjectType; } Object[] cas = (Object[])Array.CreateInstance(caType, caCount); caNext = caItem; for (int i = 0; i < caCount; i++) { cas[i] = caNext.GetObject(); caNext = caNext.m_next; } return(cas); } else { return((caType == null || caType.IsValueType) ? s_gObjectEmptyArray : (Object[])Array.CreateInstance(caType, 0)); } }
// does some consisitency check between the CA list and every CA attribute usage and after // discarding unwanted CA return an array of them static private Object[] CheckConsistencyAndCreateArray(CustomAttribute caItem, Type caType) { // we got the max number of attributes, we may have to trim this list but let's get a count for now if (caItem == null) return (caType == null || caType.IsValueType) ? s_gObjectEmptyArray : (Object[])Array.CreateInstance(caType, 0); int caCount = 0; int hasInherited = (caItem == null) ? 0 : caItem.m_inheritLevel; CustomAttribute caNext = caItem; CustomAttribute caPrev = null; // walk and revert the list while (caNext != null) { caCount++; CustomAttribute caTemp = caNext.m_next; caNext.m_next = caPrev; caPrev = caNext; caNext = caTemp; } caItem = caPrev; // now we have a list of custom attribute of some type. That list may contain subtype of the specific // type, so for every other type we have to go and check whether multiple and inherited are respected if (caCount > 0 && hasInherited > 0) { // keep track of the CA types so we can make inspection reasonable fast Hashtable htCAData = new Hashtable(11); // loop through the list of attributes checking for consistency, once an attribute // has been inspected is never going to be looked at again, and neither an attribute // of the same type. // This loop and the inspectedCATypes array should make that happen caNext = caItem; CustomAttribute caLast = null; while (caNext != null) { AttributeUsageAttribute usage = null; int caTypeLevelFound = 0; // get current attribute type Type t = caNext.GetAttributeType(); // look if the type has already been seen CAData caData = (CAData)htCAData[t]; if (caData != null) { usage = caData.usage; caTypeLevelFound = caData.level; } if (usage == null) // no type found, load the attribute usage // do not save the attribute usage yet because the next block may discard // the attribute which implies we pretend we never saw. That is kind of // bad because we may end up reloading it again if another type comes into the picture // but we prefer the perf hit to more code complication for a case that seem to // be submarginal usage = CustomAttribute.GetAttributeUsage(t); // if this is an inherited attribute and the attribute usage does not allow that, OR // if the attribute was seen already on a different inheritance level and multiple is not allowed // THEN discard if ((caNext.m_inheritLevel > 0 && !usage.Inherited) || (caData != null && caTypeLevelFound < caNext.m_inheritLevel && !usage.AllowMultiple)) { if (caLast == null) caItem = caNext.m_next; else caLast.m_next = caNext.m_next; caNext = caNext.m_next; caCount--; continue; } if (caData == null) // the attribute was never seen so far so we should add it to the table and keep going htCAData[t] = new CAData(t, usage, caNext.m_inheritLevel); caLast = caNext; caNext = caNext.m_next; } } // time to return the array if (caCount > 0) { if (caType == null || caType.IsValueType) caType = s_ObjectType; Object[] cas = (Object[])Array.CreateInstance(caType, caCount); caNext = caItem; for (int i = 0; i < caCount; i++) { cas[i] = caNext.GetObject(); caNext = caNext.m_next; } return cas; } else return (caType == null || caType.IsValueType) ? s_gObjectEmptyArray : (Object[])Array.CreateInstance(caType, 0); }