Assembly.cs 16 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 => throw NotImplemented.ByDesign;
  65. public virtual MethodInfo? EntryPoint => throw NotImplemented.ByDesign;
  66. public virtual string? FullName => throw NotImplemented.ByDesign;
  67. public virtual string ImageRuntimeVersion => throw NotImplemented.ByDesign;
  68. public virtual bool IsDynamic => false;
  69. public virtual string Location => throw NotImplemented.ByDesign;
  70. public virtual bool ReflectionOnly => 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 => 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 => throw NotImplemented.ByDesign;
  120. public virtual long HostContext => 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) => !(left == right);
  141. public static string CreateQualifiedName(string? assemblyName, string? typeName) => typeName + ", " + assemblyName;
  142. public static Assembly? GetAssembly(Type type)
  143. {
  144. if (type == null)
  145. throw new ArgumentNullException(nameof(type));
  146. Module m = type.Module;
  147. if (m == null)
  148. return null;
  149. else
  150. return m.Assembly;
  151. }
  152. public static Assembly Load(byte[] rawAssembly) => Load(rawAssembly, rawSymbolStore: null);
  153. // Loads the assembly with a COFF based IMAGE containing
  154. // an emitted assembly. The assembly is loaded into a fully isolated ALC with resolution fully deferred to the AssemblyLoadContext.Default.
  155. // The second parameter is the raw bytes representing the symbol store that matches the assembly.
  156. public static Assembly Load(byte[] rawAssembly, byte[]? rawSymbolStore)
  157. {
  158. if (rawAssembly == null)
  159. throw new ArgumentNullException(nameof(rawAssembly));
  160. if (rawAssembly.Length == 0)
  161. throw new BadImageFormatException(SR.BadImageFormat_BadILFormat);
  162. SerializationInfo.ThrowIfDeserializationInProgress("AllowAssembliesFromByteArrays",
  163. ref s_cachedSerializationSwitch);
  164. AssemblyLoadContext alc = new IndividualAssemblyLoadContext("Assembly.Load(byte[], ...)");
  165. return alc.InternalLoad(rawAssembly, rawSymbolStore);
  166. }
  167. public static Assembly LoadFile(string path)
  168. {
  169. if (path == null)
  170. throw new ArgumentNullException(nameof(path));
  171. if (PathInternal.IsPartiallyQualified(path))
  172. {
  173. throw new ArgumentException(SR.Format(SR.Argument_AbsolutePathRequired, path), nameof(path));
  174. }
  175. string normalizedPath = Path.GetFullPath(path);
  176. Assembly? result;
  177. lock (s_loadfile)
  178. {
  179. if (s_loadfile.TryGetValue(normalizedPath, out result))
  180. return result;
  181. AssemblyLoadContext alc = new IndividualAssemblyLoadContext(string.Format("Assembly.LoadFile({0})", normalizedPath));
  182. result = alc.LoadFromAssemblyPath(normalizedPath);
  183. s_loadfile.Add(normalizedPath, result);
  184. }
  185. return result;
  186. }
  187. private static Assembly? LoadFromResolveHandler(object? sender, ResolveEventArgs args)
  188. {
  189. Assembly? requestingAssembly = args.RequestingAssembly;
  190. if (requestingAssembly == null)
  191. {
  192. return null;
  193. }
  194. // Requesting assembly for LoadFrom is always loaded in defaultContext - proceed only if that
  195. // is the case.
  196. if (AssemblyLoadContext.Default != AssemblyLoadContext.GetLoadContext(requestingAssembly))
  197. return null;
  198. // Get the path where requesting assembly lives and check if it is in the list
  199. // of assemblies for which LoadFrom was invoked.
  200. string requestorPath = Path.GetFullPath(requestingAssembly.Location);
  201. if (string.IsNullOrEmpty(requestorPath))
  202. return null;
  203. lock (s_loadFromAssemblyList)
  204. {
  205. // If the requestor assembly was not loaded using LoadFrom, exit.
  206. if (!s_loadFromAssemblyList.Contains(requestorPath))
  207. {
  208. #if CORECLR
  209. if (AssemblyLoadContext.IsTracingEnabled())
  210. {
  211. AssemblyLoadContext.TraceAssemblyLoadFromResolveHandlerInvoked(args.Name, false, requestorPath, null);
  212. }
  213. #endif // CORECLR
  214. return null;
  215. }
  216. }
  217. // Requestor assembly was loaded using loadFrom, so look for its dependencies
  218. // in the same folder as it.
  219. // Form the name of the assembly using the path of the assembly that requested its load.
  220. AssemblyName requestedAssemblyName = new AssemblyName(args.Name!);
  221. string requestedAssemblyPath = Path.Combine(Path.GetDirectoryName(requestorPath)!, requestedAssemblyName.Name + ".dll");
  222. #if CORECLR
  223. if (AssemblyLoadContext.IsTracingEnabled())
  224. {
  225. AssemblyLoadContext.TraceAssemblyLoadFromResolveHandlerInvoked(args.Name, true, requestorPath, requestedAssemblyPath);
  226. }
  227. #endif // CORECLR
  228. try
  229. {
  230. // Load the dependency via LoadFrom so that it goes through the same path of being in the LoadFrom list.
  231. return Assembly.LoadFrom(requestedAssemblyPath);
  232. }
  233. catch (FileNotFoundException)
  234. {
  235. // Catch FileNotFoundException when attempting to resolve assemblies via this handler to account for missing assemblies.
  236. return null;
  237. }
  238. }
  239. public static Assembly LoadFrom(string assemblyFile)
  240. {
  241. if (assemblyFile == null)
  242. throw new ArgumentNullException(nameof(assemblyFile));
  243. string fullPath = Path.GetFullPath(assemblyFile);
  244. if (!s_loadFromHandlerSet)
  245. {
  246. lock (s_loadFromAssemblyList)
  247. {
  248. if (!s_loadFromHandlerSet)
  249. {
  250. AssemblyLoadContext.AssemblyResolve += LoadFromResolveHandler!;
  251. s_loadFromHandlerSet = true;
  252. }
  253. }
  254. }
  255. // Add the path to the LoadFrom path list which we will consult
  256. // before handling the resolves in our handler.
  257. lock (s_loadFromAssemblyList)
  258. {
  259. if (!s_loadFromAssemblyList.Contains(fullPath))
  260. {
  261. s_loadFromAssemblyList.Add(fullPath);
  262. }
  263. }
  264. return AssemblyLoadContext.Default.LoadFromAssemblyPath(fullPath);
  265. }
  266. public static Assembly LoadFrom(string assemblyFile, byte[]? hashValue, AssemblyHashAlgorithm hashAlgorithm)
  267. {
  268. throw new NotSupportedException(SR.NotSupported_AssemblyLoadFromHash);
  269. }
  270. public static Assembly UnsafeLoadFrom(string assemblyFile) => LoadFrom(assemblyFile);
  271. public Module LoadModule(string moduleName, byte[]? rawModule) => LoadModule(moduleName, rawModule, null);
  272. public virtual Module LoadModule(string moduleName, byte[]? rawModule, byte[]? rawSymbolStore) { throw NotImplemented.ByDesign; }
  273. public static Assembly ReflectionOnlyLoad(byte[] rawAssembly) { throw new PlatformNotSupportedException(SR.PlatformNotSupported_ReflectionOnly); }
  274. public static Assembly ReflectionOnlyLoad(string assemblyString) { throw new PlatformNotSupportedException(SR.PlatformNotSupported_ReflectionOnly); }
  275. public static Assembly ReflectionOnlyLoadFrom(string assemblyFile) { throw new PlatformNotSupportedException(SR.PlatformNotSupported_ReflectionOnly); }
  276. public virtual SecurityRuleSet SecurityRuleSet => SecurityRuleSet.None;
  277. }
  278. }