/// <summary> /// Compares two assembly names /// </summary> /// <param name="a">First assembly name</param> /// <param name="b">Second assembly name</param> /// <returns></returns> public bool Equals(IDmdAssemblyName a, IDmdAssemblyName b) { if ((object)a == b) { return(true); } if ((object)a == null || (object)b == null) { return(false); } // We do not compare the version number. The runtime can redirect an assembly // reference from a requested version to any other version. // The public key token is also ignored. Only .NET Framwork checks it (.NET Core // and Unity ignore it). We could add a new option to ignore the PKT but it would // require too many changes to the code (they access singleton comparers) and isn't // worth it. It's also being replaced by .NET Core. It's not common for two // assemblies loaded in the same process to have the same assembly name but a // different public key token. const DmdAssemblyNameFlags flagsMask = DmdAssemblyNameFlags.ContentType_Mask; return((a.RawFlags & flagsMask) == (b.RawFlags & flagsMask) && StringComparer.OrdinalIgnoreCase.Equals(a.Name, b.Name) && StringComparer.OrdinalIgnoreCase.Equals(a.CultureName ?? string.Empty, b.CultureName ?? string.Empty)); }
/// <summary> /// Constructor /// </summary> /// <param name="name">Simple name</param> /// <param name="version">Version</param> /// <param name="cultureName">Culture or null</param> /// <param name="flags">Flags</param> /// <param name="publicKey">Public key or null</param> /// <param name="publicKeyToken">Public key token or null</param> /// <param name="hashAlgorithm">Hash algorithm</param> public DmdReadOnlyAssemblyName(string name, Version version, string cultureName, DmdAssemblyNameFlags flags, byte[] publicKey, byte[] publicKeyToken, DmdAssemblyHashAlgorithm hashAlgorithm) { Name = name; Version = version; CultureName = cultureName; RawFlags = flags; this.publicKey = publicKey; this.publicKeyToken = publicKeyToken; HashAlgorithm = hashAlgorithm; }
/// <summary> /// Constructor /// </summary> /// <param name="name">Simple name</param> /// <param name="version">Version</param> /// <param name="cultureName">Culture or null</param> /// <param name="flags">Flags</param> /// <param name="publicKeyOrToken">Public key or public key token or null</param> /// <param name="hashAlgorithm">Hash algorithm</param> public DmdReadOnlyAssemblyName(string name, Version version, string cultureName, DmdAssemblyNameFlags flags, byte[] publicKeyOrToken, DmdAssemblyHashAlgorithm hashAlgorithm) { Name = name; Version = version; CultureName = cultureName; RawFlags = flags; if ((flags & DmdAssemblyNameFlags.PublicKey) != 0) { publicKey = publicKeyOrToken; } else { publicKeyToken = publicKeyOrToken; } HashAlgorithm = hashAlgorithm; }
/// <summary> /// Compares two assembly names /// </summary> /// <param name="a">First assembly name</param> /// <param name="b">Second assembly name</param> /// <returns></returns> public bool Equals(IDmdAssemblyName a, IDmdAssemblyName b) { if ((object)a == b) { return(true); } if ((object)a == null || (object)b == null) { return(false); } // We do not compare the version number. The runtime can redirect an assembly // reference from a requested version to any other version. const DmdAssemblyNameFlags flagsMask = DmdAssemblyNameFlags.ContentType_Mask; return((a.RawFlags & flagsMask) == (b.RawFlags & flagsMask) && StringComparer.OrdinalIgnoreCase.Equals(a.Name, b.Name) && StringComparer.OrdinalIgnoreCase.Equals(a.CultureName ?? string.Empty, b.CultureName ?? string.Empty) && Impl.AssemblyNameEqualityComparer.PublicKeyTokenEquals(a.GetPublicKeyToken(), b.GetPublicKeyToken())); }
public static void Format(StringBuilder sb, string name, Version version, string culture, byte[] publicKeyOrToken, DmdAssemblyNameFlags attributes, bool isPublicKeyToken) { if (name == null) { return; } foreach (var c in name) { if (c == ',' || c == '=') { sb.Append('\\'); } sb.Append(c); } if (version != null) { sb.Append(", Version="); sb.Append(version.ToString()); } if (culture != null) { sb.Append(", Culture="); sb.Append(string.IsNullOrEmpty(culture) ? "neutral" : culture); } if (publicKeyOrToken != null) { sb.Append(isPublicKeyToken ? ", PublicKeyToken=" : ", PublicKey="); if (publicKeyOrToken.Length == 0) { sb.Append("null"); } else { WritHex(sb, publicKeyOrToken, upper: false); } } if ((attributes & DmdAssemblyNameFlags.Retargetable) != 0) { sb.Append(", Retargetable=Yes"); } if ((attributes & DmdAssemblyNameFlags.ContentType_Mask) == DmdAssemblyNameFlags.ContentType_WindowsRuntime) { sb.Append(", ContentType=WindowsRuntime"); } }
public static string Format(string name, Version version, string culture, byte[] publicKeyOrToken, DmdAssemblyNameFlags attributes, bool isPublicKeyToken) { var sb = ObjectPools.AllocStringBuilder(); Format(sb, name, version, culture, publicKeyOrToken, attributes, isPublicKeyToken); return(ObjectPools.FreeAndToString(ref sb)); }
void ReadAssemblyRef(out string name, out Version?version, out string?cultureName, out DmdAssemblyNameFlags flags, out byte[]?publicKey, out byte[]?publicKeyToken, out DmdAssemblyHashAlgorithm hashAlgorithm) { name = ReadAssemblyNameId(); version = null; cultureName = null; flags = 0; publicKey = null; publicKeyToken = null; hashAlgorithm = DmdAssemblyHashAlgorithm.None; SkipWhite(); if (PeekChar() != ',') { return; } ReadChar(); while (true) { SkipWhite(); int c = PeekChar(); if (c == -1 || c == ']') { break; } if (c == ',') { ReadChar(); continue; } string key = ReadId(); SkipWhite(); if (PeekChar() != '=') { continue; } ReadChar(); string value = ReadId(); switch (key.ToUpperInvariant()) { case "VERSION": if (!Version.TryParse(value, out version)) { version = null; } break; case "CONTENTTYPE": if (StringComparer.OrdinalIgnoreCase.Equals(value, "WindowsRuntime")) { flags = (flags & ~DmdAssemblyNameFlags.ContentType_Mask) | DmdAssemblyNameFlags.ContentType_WindowsRuntime; } else { flags = (flags & ~DmdAssemblyNameFlags.ContentType_Mask) | DmdAssemblyNameFlags.ContentType_Default; } break; case "RETARGETABLE": if (StringComparer.OrdinalIgnoreCase.Equals(value, "Yes")) { flags |= DmdAssemblyNameFlags.Retargetable; } else { flags &= ~DmdAssemblyNameFlags.Retargetable; } break; case "PUBLICKEY": flags |= DmdAssemblyNameFlags.PublicKey; if (StringComparer.OrdinalIgnoreCase.Equals(value, "null") || StringComparer.OrdinalIgnoreCase.Equals(value, "neutral")) { publicKey = Array.Empty <byte>(); } else { publicKey = HexUtils.ParseBytes(value); } break; case "PUBLICKEYTOKEN": if (StringComparer.OrdinalIgnoreCase.Equals(value, "null") || StringComparer.OrdinalIgnoreCase.Equals(value, "neutral")) { publicKeyToken = Array.Empty <byte>(); } else { publicKeyToken = HexUtils.ParseBytes(value); } break; case "CULTURE": case "LANGUAGE": if (StringComparer.OrdinalIgnoreCase.Equals(value, "neutral")) { cultureName = string.Empty; } else { cultureName = value; } break; } } }
public static void ParseAssemblyName(string asmFullName, out string?name, out Version?version, out string?cultureName, out DmdAssemblyNameFlags flags, out byte[]?publicKey, out byte[]?publicKeyToken, out DmdAssemblyHashAlgorithm hashAlgorithm) { if (asmFullName is null) { throw new ArgumentNullException(nameof(asmFullName)); } try { using (var parser = new DmdTypeNameParser((DmdModule?)null, asmFullName, null)) parser.ReadAssemblyRef(out name, out version, out cultureName, out flags, out publicKey, out publicKeyToken, out hashAlgorithm); return; } catch { } name = null; version = null; cultureName = null; flags = 0; publicKey = null; publicKeyToken = null; hashAlgorithm = 0; }