Assembly.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  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. using System.IO;
  5. using System.Globalization;
  6. using System.Collections.Generic;
  7. using System.Configuration.Assemblies;
  8. using System.Runtime.Serialization;
  9. using System.Security;
  10. using System.Runtime.CompilerServices;
  11. using System.Runtime.Loader;
  12. namespace System.Reflection
  13. {
  14. public abstract partial class Assembly : ICustomAttributeProvider, ISerializable
  15. {
  16. private static readonly Dictionary<string, Assembly> s_loadfile = new Dictionary<string, Assembly>();
  17. private static readonly List<string> s_loadFromAssemblyList = new List<string>();
  18. private static bool s_loadFromHandlerSet;
  19. private static int s_cachedSerializationSwitch;
  20. protected Assembly() { }
  21. public virtual IEnumerable<TypeInfo> DefinedTypes
  22. {
  23. get
  24. {
  25. Type[] types = GetTypes();
  26. TypeInfo[] typeinfos = new TypeInfo[types.Length];
  27. for (int i = 0; i < types.Length; i++)
  28. {
  29. TypeInfo typeinfo = types[i].GetTypeInfo();
  30. if (typeinfo == null)
  31. throw new NotSupportedException(SR.Format(SR.NotSupported_NoTypeInfo, types[i].FullName));
  32. typeinfos[i] = typeinfo;
  33. }
  34. return typeinfos;
  35. }
  36. }
  37. public virtual Type[] GetTypes()
  38. {
  39. Module[] m = GetModules(false);
  40. if (m.Length == 1)
  41. {
  42. return m[0].GetTypes();
  43. }
  44. int finalLength = 0;
  45. Type[][] moduleTypes = new Type[m.Length][];
  46. for (int i = 0; i < moduleTypes.Length; i++)
  47. {
  48. moduleTypes[i] = m[i].GetTypes();
  49. finalLength += moduleTypes[i].Length;
  50. }
  51. int current = 0;
  52. Type[] ret = new Type[finalLength];
  53. for (int i = 0; i < moduleTypes.Length; i++)
  54. {
  55. int length = moduleTypes[i].Length;
  56. Array.Copy(moduleTypes[i], 0, ret, current, length);
  57. current += length;
  58. }
  59. return ret;
  60. }
  61. public virtual IEnumerable<Type> ExportedTypes => GetExportedTypes();
  62. public virtual Type[] GetExportedTypes() { throw NotImplemented.ByDesign; }
  63. public virtual Type[] GetForwardedTypes() { throw NotImplemented.ByDesign; }
  64. public virtual string? CodeBase { get { throw NotImplemented.ByDesign; } }
  65. public virtual MethodInfo? EntryPoint { get { throw NotImplemented.ByDesign; } }
  66. public virtual string? FullName { get { throw NotImplemented.ByDesign; } }
  67. public virtual string ImageRuntimeVersion { get { throw NotImplemented.ByDesign; } }
  68. public virtual bool IsDynamic => false;
  69. public virtual string Location { get { throw NotImplemented.ByDesign; } }
  70. public virtual bool ReflectionOnly { get { throw NotImplemented.ByDesign; } }
  71. public virtual bool IsCollectible => true;
  72. public virtual ManifestResourceInfo? GetManifestResourceInfo(string resourceName) { throw NotImplemented.ByDesign; }
  73. public virtual string[] GetManifestResourceNames() { throw NotImplemented.ByDesign; }
  74. public virtual Stream? GetManifestResourceStream(string name) { throw NotImplemented.ByDesign; }
  75. public virtual Stream? GetManifestResourceStream(Type type, string name) { throw NotImplemented.ByDesign; }
  76. public bool IsFullyTrusted => true;
  77. public virtual AssemblyName GetName() => GetName(copiedName: false);
  78. public virtual AssemblyName GetName(bool copiedName) { throw NotImplemented.ByDesign; }
  79. public virtual Type? GetType(string name) => GetType(name, throwOnError: false, ignoreCase: false);
  80. public virtual Type? GetType(string name, bool throwOnError) => GetType(name, throwOnError: throwOnError, ignoreCase: false);
  81. public virtual Type? GetType(string name, bool throwOnError, bool ignoreCase) { throw NotImplemented.ByDesign; }
  82. public virtual bool IsDefined(Type attributeType, bool inherit) { throw NotImplemented.ByDesign; }
  83. public virtual IEnumerable<CustomAttributeData> CustomAttributes => GetCustomAttributesData();
  84. public virtual IList<CustomAttributeData> GetCustomAttributesData() { throw NotImplemented.ByDesign; }
  85. public virtual object[] GetCustomAttributes(bool inherit) { throw NotImplemented.ByDesign; }
  86. public virtual object[] GetCustomAttributes(Type attributeType, bool inherit) { throw NotImplemented.ByDesign; }
  87. public virtual string EscapedCodeBase => AssemblyName.EscapeCodeBase(CodeBase);
  88. public object? CreateInstance(string typeName) => CreateInstance(typeName, false, BindingFlags.Public | BindingFlags.Instance, binder: null, args: null, culture: null, activationAttributes: null);
  89. public object? CreateInstance(string typeName, bool ignoreCase) => CreateInstance(typeName, ignoreCase, BindingFlags.Public | BindingFlags.Instance, binder: null, args: null, culture: null, activationAttributes: null);
  90. public virtual object? CreateInstance(string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder? binder, object[]? args, CultureInfo? culture, object[]? activationAttributes)
  91. {
  92. Type? t = GetType(typeName, throwOnError: false, ignoreCase: ignoreCase);
  93. if (t == null)
  94. return null;
  95. return Activator.CreateInstance(t, bindingAttr, binder, args, culture, activationAttributes);
  96. }
  97. public virtual event ModuleResolveEventHandler? ModuleResolve { add { throw NotImplemented.ByDesign; } remove { throw NotImplemented.ByDesign; } }
  98. public virtual Module ManifestModule { get { throw NotImplemented.ByDesign; } }
  99. public virtual Module? GetModule(string name) { throw NotImplemented.ByDesign; }
  100. public Module[] GetModules() => GetModules(getResourceModules: false);
  101. public virtual Module[] GetModules(bool getResourceModules) { throw NotImplemented.ByDesign; }
  102. public virtual IEnumerable<Module> Modules => GetLoadedModules(getResourceModules: true);
  103. public Module[] GetLoadedModules() => GetLoadedModules(getResourceModules: false);
  104. public virtual Module[] GetLoadedModules(bool getResourceModules) { throw NotImplemented.ByDesign; }
  105. public virtual AssemblyName[] GetReferencedAssemblies() { throw NotImplemented.ByDesign; }
  106. public virtual Assembly GetSatelliteAssembly(CultureInfo culture) { throw NotImplemented.ByDesign; }
  107. public virtual Assembly GetSatelliteAssembly(CultureInfo culture, Version? version) { throw NotImplemented.ByDesign; }
  108. public virtual FileStream? GetFile(string name) { throw NotImplemented.ByDesign; }
  109. public virtual FileStream[] GetFiles() => GetFiles(getResourceModules: false);
  110. public virtual FileStream[] GetFiles(bool getResourceModules) { throw NotImplemented.ByDesign; }
  111. public virtual void GetObjectData(SerializationInfo info, StreamingContext context) { throw NotImplemented.ByDesign; }
  112. public override string ToString()
  113. {
  114. return FullName ?? base.ToString()!;
  115. }
  116. /*
  117. Returns true if the assembly was loaded from the global assembly cache.
  118. */
  119. public virtual bool GlobalAssemblyCache { get { throw NotImplemented.ByDesign; } }
  120. public virtual long HostContext { get { throw NotImplemented.ByDesign; } }
  121. public override bool Equals(object? o) => base.Equals(o);
  122. public override int GetHashCode() => base.GetHashCode();
  123. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  124. public static bool operator ==(Assembly? left, Assembly? right)
  125. {
  126. // Test "right" first to allow branch elimination when inlined for null checks (== null)
  127. // so it can become a simple test
  128. if (right is null)
  129. {
  130. // return true/false not the test result https://github.com/dotnet/coreclr/issues/914
  131. return (left is null) ? true : false;
  132. }
  133. // Try fast reference equality and opposite null check prior to calling the slower virtual Equals
  134. if ((object?)left == (object)right)
  135. {
  136. return true;
  137. }
  138. return (left is null) ? false : left.Equals(right);
  139. }
  140. public static bool operator !=(Assembly? left, Assembly? right)
  141. {
  142. return !(left == right);
  143. }
  144. public static string CreateQualifiedName(string? assemblyName, string? typeName) => typeName + ", " + assemblyName;
  145. public static Assembly? GetAssembly(Type type)
  146. {
  147. if (type == null)
  148. throw new ArgumentNullException(nameof(type));
  149. Module m = type.Module;
  150. if (m == null)
  151. return null;
  152. else
  153. return m.Assembly;
  154. }
  155. public static Assembly Load(byte[] rawAssembly) => Load(rawAssembly, rawSymbolStore: null);
  156. // Loads the assembly with a COFF based IMAGE containing
  157. // an emitted assembly. The assembly is loaded into a fully isolated ALC with resolution fully deferred to the AssemblyLoadContext.Default.
  158. // The second parameter is the raw bytes representing the symbol store that matches the assembly.
  159. public static Assembly Load(byte[] rawAssembly, byte[]? rawSymbolStore)
  160. {
  161. if (rawAssembly == null)
  162. throw new ArgumentNullException(nameof(rawAssembly));
  163. if (rawAssembly.Length == 0)
  164. throw new BadImageFormatException(SR.BadImageFormat_BadILFormat);
  165. #if FEATURE_APPX
  166. if (ApplicationModel.IsUap)
  167. throw new NotSupportedException(SR.Format(SR.NotSupported_AppX, "Assembly.Load(byte[], ...)"));
  168. #endif
  169. SerializationInfo.ThrowIfDeserializationInProgress("AllowAssembliesFromByteArrays",
  170. ref s_cachedSerializationSwitch);
  171. AssemblyLoadContext alc = new IndividualAssemblyLoadContext("Assembly.Load(byte[], ...)");
  172. return alc.InternalLoad(rawAssembly, rawSymbolStore);
  173. }
  174. public static Assembly LoadFile(string path)
  175. {
  176. if (path == null)
  177. throw new ArgumentNullException(nameof(path));
  178. #if FEATURE_APPX
  179. if (ApplicationModel.IsUap)
  180. throw new NotSupportedException(SR.Format(SR.NotSupported_AppX, "Assembly.LoadFile"));
  181. #endif
  182. if (PathInternal.IsPartiallyQualified(path))
  183. {
  184. throw new ArgumentException(SR.Argument_AbsolutePathRequired, nameof(path));
  185. }
  186. string normalizedPath = Path.GetFullPath(path);
  187. Assembly? result;
  188. lock (s_loadfile)
  189. {
  190. if (s_loadfile.TryGetValue(normalizedPath, out result))
  191. return result;
  192. AssemblyLoadContext alc = new IndividualAssemblyLoadContext(string.Format("Assembly.LoadFile({0})", normalizedPath));
  193. result = alc.LoadFromAssemblyPath(normalizedPath);
  194. s_loadfile.Add(normalizedPath, result);
  195. }
  196. return result;
  197. }
  198. private static Assembly? LoadFromResolveHandler(object? sender, ResolveEventArgs args)
  199. {
  200. Assembly? requestingAssembly = args.RequestingAssembly;
  201. if (requestingAssembly == null)
  202. {
  203. return null;
  204. }
  205. // Requesting assembly for LoadFrom is always loaded in defaultContext - proceed only if that
  206. // is the case.
  207. if (AssemblyLoadContext.Default != AssemblyLoadContext.GetLoadContext(requestingAssembly))
  208. return null;
  209. // Get the path where requesting assembly lives and check if it is in the list
  210. // of assemblies for which LoadFrom was invoked.
  211. string requestorPath = Path.GetFullPath(requestingAssembly.Location);
  212. if (string.IsNullOrEmpty(requestorPath))
  213. return null;
  214. lock (s_loadFromAssemblyList)
  215. {
  216. // If the requestor assembly was not loaded using LoadFrom, exit.
  217. if (!s_loadFromAssemblyList.Contains(requestorPath))
  218. return null;
  219. }
  220. // Requestor assembly was loaded using loadFrom, so look for its dependencies
  221. // in the same folder as it.
  222. // Form the name of the assembly using the path of the assembly that requested its load.
  223. AssemblyName requestedAssemblyName = new AssemblyName(args.Name!);
  224. string requestedAssemblyPath = Path.Combine(Path.GetDirectoryName(requestorPath)!, requestedAssemblyName.Name + ".dll");
  225. try
  226. {
  227. // Load the dependency via LoadFrom so that it goes through the same path of being in the LoadFrom list.
  228. return Assembly.LoadFrom(requestedAssemblyPath);
  229. }
  230. catch (FileNotFoundException)
  231. {
  232. // Catch FileNotFoundException when attempting to resolve assemblies via this handler to account for missing assemblies.
  233. return null;
  234. }
  235. }
  236. public static Assembly LoadFrom(string assemblyFile)
  237. {
  238. if (assemblyFile == null)
  239. throw new ArgumentNullException(nameof(assemblyFile));
  240. string fullPath = Path.GetFullPath(assemblyFile);
  241. if (!s_loadFromHandlerSet)
  242. {
  243. lock (s_loadFromAssemblyList)
  244. {
  245. if (!s_loadFromHandlerSet)
  246. {
  247. AssemblyLoadContext.AssemblyResolve += LoadFromResolveHandler!;
  248. s_loadFromHandlerSet = true;
  249. }
  250. }
  251. }
  252. // Add the path to the LoadFrom path list which we will consult
  253. // before handling the resolves in our handler.
  254. lock(s_loadFromAssemblyList)
  255. {
  256. if (!s_loadFromAssemblyList.Contains(fullPath))
  257. {
  258. s_loadFromAssemblyList.Add(fullPath);
  259. }
  260. }
  261. return AssemblyLoadContext.Default.LoadFromAssemblyPath(fullPath);
  262. }
  263. public static Assembly LoadFrom(string assemblyFile, byte[]? hashValue, AssemblyHashAlgorithm hashAlgorithm)
  264. {
  265. throw new NotSupportedException(SR.NotSupported_AssemblyLoadFromHash);
  266. }
  267. public static Assembly UnsafeLoadFrom(string assemblyFile) => LoadFrom(assemblyFile);
  268. public Module LoadModule(string moduleName, byte[]? rawModule) => LoadModule(moduleName, rawModule, null);
  269. public virtual Module LoadModule(string moduleName, byte[]? rawModule, byte[]? rawSymbolStore) { throw NotImplemented.ByDesign; }
  270. public static Assembly ReflectionOnlyLoad(byte[] rawAssembly) { throw new PlatformNotSupportedException(SR.PlatformNotSupported_ReflectionOnly); }
  271. public static Assembly ReflectionOnlyLoad(string assemblyString) { throw new PlatformNotSupportedException(SR.PlatformNotSupported_ReflectionOnly); }
  272. public static Assembly ReflectionOnlyLoadFrom(string assemblyFile) { throw new PlatformNotSupportedException(SR.PlatformNotSupported_ReflectionOnly); }
  273. public virtual SecurityRuleSet SecurityRuleSet => SecurityRuleSet.None;
  274. }
  275. }