/// <summary> /// Returns a reference to the type that the given alias stands for. For example, if alias is a type forwarder, return a reference to the forwarded type (in another assembly). /// </summary> internal INamedTypeReference/*?*/ GetReferenceToAliasedType(ExportedTypeAliasBase alias) { Assembly/*?*/ thisAssembly = this.Module as Assembly; if (thisAssembly == null) return null; uint exportedTypeRowId = alias.ExportedTypeRowId; if (exportedTypeRowId == 0) return null; ExportedTypeRow exportedTypeRow = this.PEFileReader.ExportedTypeTable[exportedTypeRowId]; uint tokenType = exportedTypeRow.Implementation & TokenTypeIds.TokenTypeMask; uint rowId = exportedTypeRow.Implementation & TokenTypeIds.RIDMask; IName namespaceName = this.GetNameFromOffset(exportedTypeRow.TypeNamespace); IName mangledTypeName = this.GetNameFromOffset(exportedTypeRow.TypeName); IName unmangledTypeName = this.GetUnmangledNameFromOffset(exportedTypeRow.TypeName); switch (tokenType) { case TokenTypeIds.File: { FileReference/*?*/ fileRef = this.GetFileReferenceAt(rowId); if (fileRef == null) return null; var module = thisAssembly.FindMemberModuleNamed(fileRef.Name) as Module; if (module == null) return null; var foundType = module.PEFileToObjectModel.ResolveNamespaceTypeDefinition(namespaceName, mangledTypeName); if (foundType == null) return null; return foundType; } case TokenTypeIds.ExportedType: { ExportedTypeAliasBase/*?*/ parentExportedType = this.GetExportedTypeAtRowWorker(rowId); if (parentExportedType == null) return null; var parentModuleType = this.GetReferenceToAliasedType(parentExportedType); if (parentModuleType == null) return null; ITypeDefinition parentType = parentModuleType.ResolvedType; if (!(parentType is Dummy)) { foreach (ITypeDefinitionMember tdm in parentModuleType.ResolvedType.GetMembersNamed(unmangledTypeName, false)) { var modTypeRef = tdm as IMetadataReaderNamedTypeReference; if (modTypeRef != null) return modTypeRef; } } else { NamespaceTypeNameTypeReference/*?*/ nstr = parentModuleType as NamespaceTypeNameTypeReference; if (nstr != null) { var nestedTypeName = new NestedTypeName(this.NameTable, nstr.NamespaceTypeName, mangledTypeName); return nestedTypeName.GetAsNamedTypeReference(this, nstr.Module); } NestedTypeNameTypeReference/*?*/ netr = parentModuleType as NestedTypeNameTypeReference; if (netr != null) { var nestedTypeName = new NestedTypeName(this.NameTable, netr.NestedTypeName, mangledTypeName); return nestedTypeName.GetAsNamedTypeReference(this, netr.Module); } } return null; } case TokenTypeIds.AssemblyRef: { AssemblyReference/*?*/ assemRef = this.GetAssemblyReferenceAt(rowId); if (assemRef == null) return null; var internalAssembly = assemRef.ResolvedAssembly as Assembly; if (internalAssembly != null) { //Since we have already loaded the assembly that is supposed to hold this type, we may as well try and resolve it. PEFileToObjectModel assemblyPEFileToObjectModel = internalAssembly.PEFileToObjectModel; var type = assemblyPEFileToObjectModel.ResolveNamespaceTypeDefinition(namespaceName, mangledTypeName); if (type != null) return type; //The other assembly (internalAssembly) does not have a namespace type def for this reference. //Perhaps it has an alias that forwards to somewhere else... Not very likely happen in practice, I would hope. ExportedTypeAliasBase/*?*/ aliasType = assemblyPEFileToObjectModel.TryToResolveAsNamespaceTypeAlias(namespaceName, mangledTypeName); if (aliasType != null && aliasType != alias) return assemblyPEFileToObjectModel.GetReferenceToAliasedType(aliasType); //Although we can resolve the target assembly, we can neither resolve the aliased type, nor find a secondary alias. //This is mighty strange. Probably the host has fluffed assembly resolution and internalAssembly isn't really the //assembly we are looking for. We now have to give up and simply return an unresolved reference. } string fullTypeName = mangledTypeName.Value; if (namespaceName.Value.Length > 0) fullTypeName = namespaceName.Value+"."+fullTypeName; var parser = new TypeNameParser(this.NameTable, fullTypeName); return parser.ParseTypeName().GetAsTypeReference(this, assemRef) as INamedTypeReference; } } return null; }
NominalTypeName/*?*/ ParseNominalTypeName() { NominalTypeName/*?*/ nomTypeName = this.ParseNamespaceTypeName(); if (nomTypeName == null) return null; while (this.CurrentTypeNameTokenKind == TypeNameTokenKind.Plus) { this.NextToken(false); if (this.CurrentTypeNameTokenKind != TypeNameTokenKind.Identifier) { return null; } nomTypeName = new NestedTypeName(this.NameTable, nomTypeName, this.CurrentIdentifierInfo); this.NextToken(false); } return nomTypeName; }
/// <summary> /// Finds the given aliased type in the exported type table. /// </summary> /// <param name="aliasAliasBase"></param> /// <returns></returns> internal IModuleTypeReference/*?*/ FindExportedType( ExportedTypeAliasBase aliasAliasBase ) { Assembly/*?*/ thisAssembly = this.Module as Assembly; if (thisAssembly == null) return null; uint exportedTypeRowId = aliasAliasBase.ExportedTypeRowId; if (exportedTypeRowId == 0) return null; ExportedTypeRow exportedTypeRow = this.PEFileReader.ExportedTypeTable[exportedTypeRowId]; uint tokenType = exportedTypeRow.Implementation & TokenTypeIds.TokenTypeMask; uint rowId = exportedTypeRow.Implementation & TokenTypeIds.RIDMask; IName namespaceName = this.GetNameFromOffset(exportedTypeRow.TypeNamespace); IName typeName = this.GetNameFromOffset(exportedTypeRow.TypeName); switch (tokenType) { case TokenTypeIds.File: { FileReference/*?*/ fileRef = this.GetFileReferenceAt(rowId); if (fileRef == null) { return null; } Module/*?*/ module =thisAssembly.FindMemberModuleNamed(fileRef.Name); if (module == null) { return null; } TypeBase/*?*/ foundType = module.PEFileToObjectModel.ResolveNamespaceTypeDefinition(namespaceName, typeName); if (foundType == null) { return null; } return foundType; } case TokenTypeIds.ExportedType: { ExportedTypeAliasBase/*?*/ parentExportedType = this.GetExportedTypeAtRowWorker(rowId); if (parentExportedType == null) { return null; } IModuleTypeReference/*?*/ parentModuleType = this.FindExportedType(parentExportedType); if (parentModuleType == null) { return null; } ITypeDefinition parentType = parentModuleType.ResolvedType; if (parentType != Dummy.Type) { foreach (ITypeDefinitionMember tdm in parentModuleType.ResolvedType.GetMembersNamed(typeName, false)) { IModuleTypeReference/*?*/ modTypeRef = tdm as IModuleTypeReference; if (modTypeRef != null) return modTypeRef; } } else { NamespaceTypeNameTypeReference/*?*/ nstr = parentModuleType as NamespaceTypeNameTypeReference; if (nstr != null) { var nestedTypeName = new NestedTypeName(this.NameTable, nstr.NamespaceTypeName, typeName); return nestedTypeName.GetAsTypeReference(this, nstr.Module); } NestedTypeNameTypeReference/*?*/ netr = parentModuleType as NestedTypeNameTypeReference; if (netr != null) { var nestedTypeName = new NestedTypeName(this.NameTable, netr.NestedTypeName, typeName); return nestedTypeName.GetAsTypeReference(this, netr.Module); } } return null; } case TokenTypeIds.AssemblyRef: { AssemblyReference/*?*/ assemRef = this.GetAssemblyReferenceAt(rowId); if (assemRef == null) { return null; } var internalAssembly = assemRef.ResolvedAssembly as Assembly; if (internalAssembly != null) { PEFileToObjectModel assemblyPEFileToObjectModel = internalAssembly.PEFileToObjectModel; TypeBase/*?*/ type = assemblyPEFileToObjectModel.ResolveNamespaceTypeDefinition(namespaceName, typeName); if (type != null) return type; ExportedTypeAliasBase/*?*/ aliasType = assemblyPEFileToObjectModel.ResolveExportedNamespaceType(namespaceName, typeName); if (aliasType != null && aliasType != aliasAliasBase) { return assemblyPEFileToObjectModel.FindExportedType(aliasType); } } else { string fullTypeName = typeName.Value; if (namespaceName.Value.Length > 0) fullTypeName = namespaceName.Value+"."+typeName.Value; var parser = new TypeNameParser(this.NameTable, fullTypeName); return parser.ParseTypeName().GetAsTypeReference(this, assemRef); } } break; } return null; }