public override DefType[] ComputeRuntimeInterfaces(TypeDesc _type) { ArrayType arrayType = (ArrayType)_type; Debug.Assert(arrayType.IsSzArray); TypeDesc arrayOfTInstantiation = _arrayOfTType.MakeInstantiatedType(arrayType.ElementType); return(arrayOfTInstantiation.RuntimeInterfaces); }
/// <summary> /// Parses the string '<paramref name="name"/>' and returns the type corresponding to the parsed type name. /// The type name string should be in the 'SerString' format as defined by the ECMA-335 standard. /// This is the inverse of what <see cref="CustomAttributeTypeNameFormatter"/> does. /// </summary> public static TypeDesc GetTypeByCustomAttributeTypeName(this ModuleDesc module, string name, bool throwIfNotFound = true, Func <string, ModuleDesc, bool, MetadataType> resolver = null) { TypeDesc loadedType; StringBuilder genericTypeDefName = new StringBuilder(name.Length); var ch = name.Begin(); var nameEnd = name.End(); for (; ch < nameEnd; ++ch) { // Always pass escaped characters through. if (ch.Current == '\\') { genericTypeDefName.Append(ch.Current); ++ch; if (ch < nameEnd) { genericTypeDefName.Append(ch.Current); } continue; } // The type def name ends if // The start of a generic argument list if (ch.Current == '[') { break; } // Indication that the type is a pointer if (ch.Current == '*') { break; } // Indication that the type is a reference if (ch.Current == '&') { break; } // A comma that indicates that the rest of the name is an assembly reference if (ch.Current == ',') { break; } genericTypeDefName.Append(ch.Current); } ModuleDesc homeModule = module; AssemblyName homeAssembly = FindAssemblyIfNamePresent(name); if (homeAssembly != null) { homeModule = module.Context.ResolveAssembly(homeAssembly); } MetadataType typeDef = resolver != null?resolver(genericTypeDefName.ToString(), homeModule, throwIfNotFound) : ResolveCustomAttributeTypeDefinitionName(genericTypeDefName.ToString(), homeModule, throwIfNotFound); if (typeDef == null) { return(null); } ArrayBuilder <TypeDesc> genericArgs = new ArrayBuilder <TypeDesc>(); // Followed by generic instantiation parameters (but check for the array case) if (ch < nameEnd && ch.Current == '[' && (ch + 1) < nameEnd && (ch + 1).Current != ']' && (ch + 1).Current != ',') { ch++; // truncate the '[' var genericInstantiationEnd = ch + ReadTypeArgument(ch, nameEnd, true); // find the end of the instantiation list while (ch < genericInstantiationEnd) { if (ch.Current == ',') { ch++; } int argLen = ReadTypeArgument(ch, name.End(), false); string typeArgName; if (ch.Current == '[') { // This type argument name is stringified, // we need to remove the [] from around it ch++; typeArgName = StringIterator.Substring(ch, ch + (argLen - 2)); ch += argLen - 1; } else { typeArgName = StringIterator.Substring(ch, ch + argLen); ch += argLen; } TypeDesc argType = module.GetTypeByCustomAttributeTypeName(typeArgName, throwIfNotFound, resolver); if (argType == null) { return(null); } genericArgs.Add(argType); } Debug.Assert(ch == genericInstantiationEnd); ch++; loadedType = typeDef.MakeInstantiatedType(genericArgs.ToArray()); } else { // Non-generic type loadedType = typeDef; } // At this point the characters following may be any number of * characters to indicate pointer depth while (ch < nameEnd) { if (ch.Current == '*') { loadedType = loadedType.MakePointerType(); } else { break; } ch++; } // Followed by any number of "[]" or "[,*]" pairs to indicate arrays int commasSeen = 0; bool bracketSeen = false; while (ch < nameEnd) { if (ch.Current == '[') { ch++; commasSeen = 0; bracketSeen = true; } else if (ch.Current == ']') { if (!bracketSeen) { break; } ch++; if (commasSeen == 0) { loadedType = loadedType.MakeArrayType(); } else { loadedType = loadedType.MakeArrayType(commasSeen + 1); } bracketSeen = false; } else if (ch.Current == ',') { if (!bracketSeen) { break; } ch++; commasSeen++; } else { break; } } // Followed by at most one & character to indicate a byref. if (ch < nameEnd) { if (ch.Current == '&') { loadedType = loadedType.MakeByRefType(); ch++; } } return(loadedType); }