Assembly.cs 16 KB

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