private Dictionary <string, List <ImmutableArray <byte> > > BuildInternalsVisibleToMap() { var ivtMap = new Dictionary <string, List <ImmutableArray <byte> > >(StringComparer.OrdinalIgnoreCase); foreach (string attrVal in Modules[0].GetInternalsVisibleToAttributeValues(Handle)) { AssemblyIdentity identity; if (AssemblyIdentity.TryParseDisplayName(attrVal, out identity)) { List <ImmutableArray <byte> > keys; if (ivtMap.TryGetValue(identity.Name, out keys)) { keys.Add(identity.PublicKey); } else { keys = new List <ImmutableArray <byte> >(); keys.Add(identity.PublicKey); ivtMap[identity.Name] = keys; } } else { // Dev10 C# reports WRN_InvalidAssemblyName and Dev10 VB reports ERR_FriendAssemblyNameInvalid but // we have no way to do that from here. Since the absence of these diagnostics does not impact the // user experience enough to justify the work required to produce them, we will simply omit them // (DevDiv #15099, #14348). } } return(ivtMap); }
public Assembly Load(string displayName) { if (!AssemblyIdentity.TryParseDisplayName(displayName, out var requestedIdentity)) { return(null); } ImmutableArray <string> candidatePaths; lock (_guard) { // First, check if this loader already loaded the requested assembly: if (_loadedAssembliesByIdentity.TryGetValue(requestedIdentity, out var existingAssembly)) { return(existingAssembly); } // Second, check if an assembly file of the same simple name was registered with the loader: if (!_knownAssemblyPathsBySimpleName.TryGetValue(requestedIdentity.Name, out var pathList)) { return(null); } Debug.Assert(pathList.Count > 0); candidatePaths = pathList.ToImmutableArray(); } // Multiple assemblies of the same simple name but different identities might have been registered. // Load the one that matches the requested identity (if any). foreach (var candidatePath in candidatePaths) { var candidateIdentity = GetOrAddAssemblyIdentity(candidatePath); if (requestedIdentity.Equals(candidateIdentity)) { return(LoadFromPathUncheckedCore(candidatePath, candidateIdentity)); } } return(null); }
// internal for testing internal ComparisonResult Compare(AssemblyIdentity reference, string referenceDisplayName, AssemblyIdentity definition, out bool unificationApplied, bool ignoreVersion) { Debug.Assert((reference != null) ^ (referenceDisplayName != null)); unificationApplied = false; AssemblyIdentityParts parts; if (reference != null) { // fast path bool?eq = TriviallyEquivalent(reference, definition); if (eq.HasValue) { return(eq.Value ? ComparisonResult.Equivalent : ComparisonResult.NotEquivalent); } parts = AssemblyIdentityParts.Name | AssemblyIdentityParts.Version | AssemblyIdentityParts.Culture | AssemblyIdentityParts.PublicKeyToken; } else { if (!AssemblyIdentity.TryParseDisplayName(referenceDisplayName, out reference, out parts) || reference.ContentType != definition.ContentType) { return(ComparisonResult.NotEquivalent); } } Debug.Assert(reference.ContentType == definition.ContentType); bool isDefinitionFxAssembly; if (!ApplyUnificationPolicies(ref reference, ref definition, parts, out isDefinitionFxAssembly)) { return(ComparisonResult.NotEquivalent); } if (ReferenceEquals(reference, definition)) { return(ComparisonResult.Equivalent); } bool compareCulture = (parts & AssemblyIdentityParts.Culture) != 0; bool comparePublicKeyToken = (parts & AssemblyIdentityParts.PublicKeyOrToken) != 0; if (!definition.IsStrongName) { if (reference.IsStrongName) { return(ComparisonResult.NotEquivalent); } if (!AssemblyIdentity.IsFullName(parts)) { if (!SimpleNameComparer.Equals(reference.Name, definition.Name)) { return(ComparisonResult.NotEquivalent); } if (compareCulture && !CultureComparer.Equals(reference.CultureName, definition.CultureName)) { return(ComparisonResult.NotEquivalent); } // version is ignored return(ComparisonResult.Equivalent); } isDefinitionFxAssembly = false; } if (!SimpleNameComparer.Equals(reference.Name, definition.Name)) { return(ComparisonResult.NotEquivalent); } if (compareCulture && !CultureComparer.Equals(reference.CultureName, definition.CultureName)) { return(ComparisonResult.NotEquivalent); } if (comparePublicKeyToken && !AssemblyIdentity.KeysEqual(reference, definition)) { return(ComparisonResult.NotEquivalent); } bool hasSomeVersionParts = (parts & AssemblyIdentityParts.Version) != 0; bool hasPartialVersion = (parts & AssemblyIdentityParts.Version) != AssemblyIdentityParts.Version; // If any version parts were specified then compare the versions. The comparison fails if some version parts are missing. if (definition.IsStrongName && hasSomeVersionParts && (hasPartialVersion || reference.Version != definition.Version)) { // Note: // System.Numerics.Vectors, Version=4.0 is an FX assembly // System.Numerics.Vectors, Version=4.1+ is not an FX assembly // // It seems like a bug in Fusion: it only determines whether the definition is an FX assembly // and calculates the result based upon that, regardless of whether the reference is an FX assembly or not. // We do replicate the behavior. // // As a result unification is asymmetric when comparing the above identities. if (isDefinitionFxAssembly) { unificationApplied = true; return(ComparisonResult.Equivalent); } if (ignoreVersion) { return(ComparisonResult.EquivalentIgnoringVersion); } return(ComparisonResult.NotEquivalent); } return(ComparisonResult.Equivalent); }
internal TypeSymbol GetTypeSymbol(MetadataHelpers.AssemblyQualifiedTypeName fullName, out bool refersToNoPiaLocalType) { // // Section 23.3 (Custom Attributes) of CLI Spec Partition II: // // If the parameter kind is System.Type, (also, the middle line in above diagram) its value is // stored as a SerString (as defined in the previous paragraph), representing its canonical name. // The canonical name is its full type name, followed optionally by the assembly where it is defined, // its version, culture and public-key-token. If the assembly name is omitted, the CLI looks first // in the current assembly, and then in the system library (mscorlib); in these two special cases, // it is permitted to omit the assembly-name, version, culture and public-key-token. int referencedAssemblyIndex; if (fullName.AssemblyName != null) { AssemblyIdentity identity; if (!AssemblyIdentity.TryParseDisplayName(fullName.AssemblyName, out identity)) { refersToNoPiaLocalType = false; return(GetUnsupportedMetadataTypeSymbol()); } // the assembly name has to be a full name: referencedAssemblyIndex = GetIndexOfReferencedAssembly(identity); if (referencedAssemblyIndex == -1) { // In rare cases (e.g. assemblies emitted by Reflection.Emit) the identity // might be the identity of the containing assembly. The metadata spec doesn't disallow this. if (!this.IsContainingAssembly(identity)) { refersToNoPiaLocalType = false; return(GetUnsupportedMetadataTypeSymbol()); } } } else { // Use this assembly referencedAssemblyIndex = -1; } // Find the top level type Debug.Assert(MetadataHelpers.IsValidMetadataIdentifier(fullName.TopLevelType)); var mdName = MetadataTypeName.FromFullName(fullName.TopLevelType); TypeSymbol container = LookupTopLevelTypeDefSymbol(ref mdName, referencedAssemblyIndex, out refersToNoPiaLocalType); // Process any nested types if (fullName.NestedTypes != null) { if (refersToNoPiaLocalType) { // Types nested into local types are not supported. refersToNoPiaLocalType = false; return(GetUnsupportedMetadataTypeSymbol()); } for (int i = 0; i < fullName.NestedTypes.Length; i++) { Debug.Assert(MetadataHelpers.IsValidMetadataIdentifier(fullName.NestedTypes[i])); mdName = MetadataTypeName.FromTypeName(fullName.NestedTypes[i]); // Find nested type in the container container = LookupNestedTypeDefSymbol(container, ref mdName); } } // Substitute type arguments if any if (fullName.TypeArguments != null) { ImmutableArray <bool> argumentRefersToNoPiaLocalType; var typeArguments = ResolveTypeArguments(fullName.TypeArguments, out argumentRefersToNoPiaLocalType); container = SubstituteTypeParameters(container, typeArguments, argumentRefersToNoPiaLocalType); foreach (bool flag in argumentRefersToNoPiaLocalType) { if (flag) { refersToNoPiaLocalType = true; break; } } } else { container = SubstituteWithUnboundIfGeneric(container); } for (int i = 0; i < fullName.PointerCount; i++) { container = MakePointerTypeSymbol(container, ImmutableArray <ModifierInfo <TypeSymbol> > .Empty); } // Process any array type ranks if (fullName.ArrayRanks != null) { foreach (int rank in fullName.ArrayRanks) { Debug.Assert(rank >= 0); container = rank == 0 ? GetSZArrayTypeSymbol(container, default(ImmutableArray <ModifierInfo <TypeSymbol> >)) : GetMDArrayTypeSymbol(rank, container, default(ImmutableArray <ModifierInfo <TypeSymbol> >), ImmutableArray <int> .Empty, default(ImmutableArray <int>)); } } return(container); }