1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System.IO; 6 using System.Reflection; 7 using System.Runtime.ExceptionServices; 8 using System.Text; 9 10 namespace System 11 { 12 [Serializable] 13 public sealed class ApplicationId 14 { 15 private readonly byte[] _publicKeyToken; 16 ApplicationId(byte[] publicKeyToken, string name, Version version, string processorArchitecture, string culture)17 public ApplicationId(byte[] publicKeyToken, string name, Version version, string processorArchitecture, string culture) 18 { 19 if (name == null) throw new ArgumentNullException(nameof(name)); 20 if (name.Length == 0) throw new ArgumentException(SR.Argument_EmptyApplicationName); 21 if (version == null) throw new ArgumentNullException(nameof(version)); 22 if (publicKeyToken == null) throw new ArgumentNullException(nameof(publicKeyToken)); 23 24 _publicKeyToken = (byte[])publicKeyToken.Clone(); 25 Name = name; 26 Version = version; 27 ProcessorArchitecture = processorArchitecture; 28 Culture = culture; 29 } 30 31 public string Culture { get; } 32 33 public string Name { get; } 34 35 public string ProcessorArchitecture { get; } 36 37 public Version Version { get; } 38 39 public byte[] PublicKeyToken => (byte[])_publicKeyToken.Clone(); 40 Copy()41 public ApplicationId Copy() => new ApplicationId(_publicKeyToken, Name, Version, ProcessorArchitecture, Culture); 42 ToString()43 public override string ToString () 44 { 45 StringBuilder sb = StringBuilderCache.Acquire(); 46 sb.Append(Name); 47 if (Culture != null) 48 { 49 sb.Append(", culture=\""); 50 sb.Append(Culture); 51 sb.Append('"'); 52 } 53 sb.Append(", version=\""); 54 sb.Append(Version.ToString()); 55 sb.Append('"'); 56 if (_publicKeyToken != null) 57 { 58 sb.Append(", publicKeyToken=\""); 59 sb.Append(EncodeHexString(_publicKeyToken)); 60 sb.Append('"'); 61 } 62 if (ProcessorArchitecture != null) 63 { 64 sb.Append(", processorArchitecture =\""); 65 sb.Append(ProcessorArchitecture); 66 sb.Append('"'); 67 } 68 return StringBuilderCache.GetStringAndRelease(sb); 69 } 70 HexDigit(int num)71 private static char HexDigit(int num) => 72 (char)((num < 10) ? (num + '0') : (num + ('A' - 10))); 73 EncodeHexString(byte[] sArray)74 private static string EncodeHexString(byte[] sArray) 75 { 76 string result = null; 77 78 if (sArray != null) 79 { 80 char[] hexOrder = new char[sArray.Length * 2]; 81 82 int digit; 83 for(int i = 0, j = 0; i < sArray.Length; i++) { 84 digit = (int)((sArray[i] & 0xf0) >> 4); 85 hexOrder[j++] = HexDigit(digit); 86 digit = (int)(sArray[i] & 0x0f); 87 hexOrder[j++] = HexDigit(digit); 88 } 89 result = new string(hexOrder); 90 } 91 return result; 92 } 93 Equals(object o)94 public override bool Equals (object o) 95 { 96 ApplicationId other = (o as ApplicationId); 97 if (other == null) 98 return false; 99 100 if (!(Equals(Name, other.Name) && 101 Equals(Version, other.Version) && 102 Equals(ProcessorArchitecture, other.ProcessorArchitecture) && 103 Equals(Culture, other.Culture))) 104 return false; 105 106 if (_publicKeyToken.Length != other._publicKeyToken.Length) 107 return false; 108 109 for (int i = 0; i < _publicKeyToken.Length; i++) 110 { 111 if (_publicKeyToken[i] != other._publicKeyToken[i]) 112 return false; 113 } 114 115 return true; 116 } 117 GetHashCode()118 public override int GetHashCode() 119 { 120 // Note: purposely skipping publicKeyToken, processor architecture and culture as they 121 // are less likely to make things not equal than name and version. 122 return Name.GetHashCode() ^ Version.GetHashCode(); 123 } 124 } 125 } 126