| File: System\Reflection\TypeLoading\Assemblies\RoAssembly.Modules.cs | Web Access |
| Project: src\runtime\src\libraries\System.Reflection.MetadataLoadContext\src\System.Reflection.MetadataLoadContext.csproj (System.Reflection.MetadataLoadContext) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Threading; namespace System.Reflection.TypeLoading { /// <summary> /// Base class for all Assembly objects created by a MetadataLoadContext. /// </summary> internal abstract partial class RoAssembly { public sealed override Module? GetModule(string name) => GetRoModule(name); public sealed override Module[] GetModules(bool getResourceModules) => ComputeRoModules(getResourceModules).CloneArray<Module>(); #if NET [RequiresAssemblyFiles(ThrowingMessageInRAF)] #endif public sealed override FileStream? GetFile(string name) { Module? m = GetModule(name); if (m == null) return null; return new FileStream(m.FullyQualifiedName, FileMode.Open, FileAccess.Read, FileShare.Read); } #if NET [RequiresAssemblyFiles(ThrowingMessageInRAF)] #endif public sealed override FileStream[] GetFiles(bool getResourceModules) { Module[] m = GetModules(getResourceModules); FileStream[] fs = new FileStream[m.Length]; for (int i = 0; i < fs.Length; i++) { fs[i] = new FileStream(m[i].FullyQualifiedName, FileMode.Open, FileAccess.Read, FileShare.Read); } return fs; } public sealed override Module[] GetLoadedModules(bool getResourceModules) { List<Module> modules = new List<Module>(_loadedModules.Length + 1) { GetRoManifestModule() }; for (int i = 0; i < _loadedModules.Length; i++) { RoModule? module = Volatile.Read(ref _loadedModules[i]); if (module != null && (getResourceModules || !module.IsResource())) modules.Add(module); } return modules.ToArray(); } public abstract override event ModuleResolveEventHandler? ModuleResolve; internal RoModule? GetRoModule(string name) { ArgumentNullException.ThrowIfNull(name); if (!TryGetAssemblyFileInfo(name, includeManifestModule: true, out AssemblyFileInfo afi)) return null; return GetRoModule(afi); } private RoModule GetRoModule(in AssemblyFileInfo afi) { if (afi.RowIndex == 0) return GetRoManifestModule(); int loadedModulesIndex = afi.RowIndex - 1; string moduleName = afi.Name; RoModule? prior = Volatile.Read(ref _loadedModules[loadedModulesIndex]); if (prior != null) return prior; RoModule newModule = LoadModule(moduleName, afi.ContainsMetadata); return Interlocked.CompareExchange(ref _loadedModules[loadedModulesIndex], newModule, null) ?? newModule; } internal RoModule[] ComputeRoModules(bool getResourceModules) { List<RoModule> modules = new List<RoModule>(_loadedModules.Length + 1); foreach (AssemblyFileInfo afi in GetAssemblyFileInfosFromManifest(includeManifestModule: true, includeResourceModules: getResourceModules)) { RoModule module = GetRoModule(afi); modules.Add(module); } return modules.ToArray(); } #pragma warning disable CS8995 // Nullable type is null-checked and will throw if null. public sealed override Module LoadModule(string moduleName, byte[]? rawModule, byte[]? rawSymbolStore) #pragma warning restore CS8995 { ArgumentNullException.ThrowIfNull(moduleName); ArgumentNullException.ThrowIfNull(rawModule); if (!TryGetAssemblyFileInfo(moduleName, includeManifestModule: false, out AssemblyFileInfo afi)) throw new ArgumentException(SR.Format(SR.SpecifiedFileNameInvalid, moduleName)); // Name not in manifest. Debug.Assert(afi.RowIndex != 0); // Since we excluded the manifest module from the search. int loadedModuleIndex = afi.RowIndex - 1; RoModule newModule = CreateModule(new MemoryStream(rawModule), afi.ContainsMetadata); Interlocked.CompareExchange(ref _loadedModules[loadedModuleIndex], newModule, null); // Somewhat shockingly, the compatible behavior is to return the newly created module always rather than the Module that // actually won the race to be resolved! return newModule; } private bool TryGetAssemblyFileInfo(string name, bool includeManifestModule, out AssemblyFileInfo afi) { foreach (AssemblyFileInfo candidate in GetAssemblyFileInfosFromManifest(includeManifestModule: includeManifestModule, includeResourceModules: true)) { if (name.Equals(candidate.Name, StringComparison.OrdinalIgnoreCase)) { afi = candidate; return true; } } afi = default; return false; } protected abstract RoModule LoadModule(string moduleName, bool containsMetadata); protected abstract RoModule CreateModule(Stream peStream, bool containsMetadata); protected abstract IEnumerable<AssemblyFileInfo> GetAssemblyFileInfosFromManifest(bool includeManifestModule, bool includeResourceModules); } }