/// <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; }
/// <summary> /// Given a alias type and type's mangled name this method resolves it to a nested aliased type. /// Aliased type can further be walked to find the exact type it resolved to. /// </summary> /// <param name="parentType"></param> /// <param name="typeName"></param> /// <returns></returns> internal ExportedTypeAliasBase/*?*/ ResolveExportedNestedType( ExportedTypeAliasBase parentType, IName typeName ) { uint exportedTypeToken = this.NestedTypeTokenTable.Find(TokenTypeIds.ExportedType | parentType.ExportedTypeRowId, (uint)typeName.UniqueKey); if (exportedTypeToken == 0 || ((exportedTypeToken & TokenTypeIds.TokenTypeMask) != TokenTypeIds.ExportedType)) { return null; } return this.GetExportedTypeAtRowWorker(exportedTypeToken & TokenTypeIds.RIDMask); }
internal void LoadNestedExportedTypesOfAlias(ExportedTypeAliasBase exportedType) { uint currentToken = exportedType.TokenValue; uint numberOfExportedTypes = this.PEFileReader.ExportedTypeTable.NumberOfRows; ExportedTypeAliasBase/*?*/[] exportedTypeArray = this.ExportedTypeArray; for (uint i = 1; i <= numberOfExportedTypes; ++i) { ExportedTypeRow exportedTypeRow = this.PEFileReader.ExportedTypeTable[i]; // Check if its in the same namespace if (exportedTypeRow.Implementation != currentToken || !exportedTypeRow.IsNested) continue; // This will not be loaded by anyone other than ExportedTypeNestedAlias/*?*/ type = (ExportedTypeNestedAlias)exportedTypeArray[i]; if (type == null) { type = this.CreateExportedNestedType(i, exportedTypeRow, exportedType); this.ExportedTypeArray[i] = type; this.ExportedTypeLoadState[i] = LoadState.Loaded; } } }
ExportedTypeNestedAlias CreateExportedNestedType( uint exportedTypeRowId, ExportedTypeRow exportedTypeRow, ExportedTypeAliasBase parentExportedType ) { IName typeName = this.GetNameFromOffset(exportedTypeRow.TypeName); ExportedTypeNestedAlias exportedType = new ExportedTypeNestedAlias(this, typeName, exportedTypeRowId, exportedTypeRow.Flags, parentExportedType); parentExportedType.AddMember(exportedType); return exportedType; }
/// <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; }
ExportedTypeNestedAlias CreateExportedNestedType(uint exportedTypeRowId, ExportedTypeRow exportedTypeRow, ExportedTypeAliasBase parentExportedType) { ExportedTypeNestedAlias exportedType = new ExportedTypeNestedAlias(this, exportedTypeRowId, exportedTypeRow.Flags, parentExportedType); parentExportedType.AddMember(exportedType); return exportedType; }