private AssemblyIdentity Port(AssemblyIdentity identity) { if (identity.IsRetargetable || !identity.IsStrongName || identity.ContentType != AssemblyContentType.Default) { return(identity); } Version newVersion = null; ImmutableArray <byte> newPublicKeyToken = default(ImmutableArray <byte>); var version = (AssemblyVersion)identity.Version; if (version >= new AssemblyVersion(2, 0, 0, 0) && version <= new AssemblyVersion(5, 9, 0, 0)) { if (identity.PublicKeyToken.SequenceEqual(s_SILVERLIGHT_PLATFORM_PUBLICKEY_STR_L)) { if (!policy.SuppressSilverlightPlatformAssembliesPortability) { if (SimpleNameComparer.Equals(identity.Name, "System") || SimpleNameComparer.Equals(identity.Name, "System.Core")) { newVersion = (Version)s_VER_ASSEMBLYVERSION_STR_L; newPublicKeyToken = s_ECMA_PUBLICKEY_STR_L; } } } else if (identity.PublicKeyToken.SequenceEqual(s_SILVERLIGHT_PUBLICKEY_STR_L)) { if (!policy.SuppressSilverlightLibraryAssembliesPortability) { if (SimpleNameComparer.Equals(identity.Name, "Microsoft.VisualBasic")) { newVersion = new Version(10, 0, 0, 0); newPublicKeyToken = s_MICROSOFT_PUBLICKEY_STR_L; } if (SimpleNameComparer.Equals(identity.Name, "System.ComponentModel.Composition")) { newVersion = (Version)s_VER_ASSEMBLYVERSION_STR_L; newPublicKeyToken = s_ECMA_PUBLICKEY_STR_L; } } } } if (newVersion == null) { return(identity); } return(new AssemblyIdentity( identity.Name, newVersion, identity.CultureName, newPublicKeyToken, hasPublicKey: false, isRetargetable: identity.IsRetargetable, contentType: AssemblyContentType.Default)); }
public bool Equals(Key other) { return(SimpleNameComparer.Equals(this.Name, other.Name) && this.PublicKeyToken.SequenceEqual(other.PublicKeyToken)); }
internal override bool ApplyUnificationPolicies( ref AssemblyIdentity reference, ref AssemblyIdentity definition, AssemblyIdentityParts referenceParts, out bool isFxAssembly) { if (reference.ContentType == AssemblyContentType.Default && SimpleNameComparer.Equals(reference.Name, definition.Name) && SimpleNameComparer.Equals(reference.Name, "mscorlib")) { isFxAssembly = true; reference = definition; return(true); } if (!reference.IsRetargetable && definition.IsRetargetable) { // Reference is not retargetable, but definition is retargetable. // Non-equivalent. isFxAssembly = false; return(false); } // Notes: // an assembly might be both retargetable and portable // in that case retargeatable table acts as an override. // Apply portability policy transforms first (e.g. rewrites references to SL assemblies to their desktop equivalents) // If the reference is partial and is missing version or PKT it is not ported. reference = Port(reference); definition = Port(definition); if (reference.IsRetargetable && !definition.IsRetargetable) { if (!AssemblyIdentity.IsFullName(referenceParts)) { isFxAssembly = false; return(false); } // Reference needs to be retargeted before comparison, // unless it's optionally retargetable and we already match the PK bool skipRetargeting = IsOptionallyRetargetableAssembly(reference) && AssemblyIdentity.KeysEqual(reference, definition); if (!skipRetargeting) { reference = Retarget(reference); } } // At this point we are in one of the following states: // // 1) Both ref/def are not retargetable // 2) Both ref/def are retargetable // 3) Ref is retargetable (and has been retargeted) // // We can do a straight compare of ref/def at this point using the // regular rules if (reference.IsRetargetable && definition.IsRetargetable) { isFxAssembly = IsRetargetableAssembly(definition); } else { isFxAssembly = IsFrameworkAssembly(definition); } return(true); }
// 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 isFxAssembly; if (!ApplyUnificationPolicies(ref reference, ref definition, parts, out isFxAssembly)) { 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); } isFxAssembly = 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)) { if (isFxAssembly) { unificationApplied = true; return(ComparisonResult.Equivalent); } if (ignoreVersion) { return(ComparisonResult.EquivalentIgnoringVersion); } return(ComparisonResult.NotEquivalent); } return(ComparisonResult.Equivalent); }
// 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); }