MetadataFile now declares IDisposable using the canonical pattern
(public non-virtual Dispose() + protected virtual Dispose(bool)).
PEFile and WebCilFile become sealed and override Dispose(bool) to
release the PEReader and MemoryMappedViewAccessor they own;
ResourcesFile is also sealed. PortableDebugInfoProvider disposes the
MetadataReaderProvider it owns. LoadedAssembly implements IDisposable
and disposes both the loaded MetadataFile and the debug-info provider.
AssemblyList.Unload / Clear / ReloadAssembly / HotReplaceAssembly now
dispose the LoadedAssembly instances they evict, fixing a resource leak
where every "Reload Assembly" held the previous PEReader (and the
underlying file handle / memory-mapped view) alive until GC eventually
finalized it.
The disposal contract terminates at the AssemblyList tier: downstream
holders of MetadataFile (MetadataModule, DecompilerTypeSystem,
AssemblyListSnapshot, ...) hold borrowed references rather than owned
ones, so making the base IDisposable does not cascade into CA1001 /
CA2213 warnings elsewhere.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* We no longer maintain the weird `loadingAssemblies` global state.
* AssemblyList now internally handles multiple concurrent load requests for the same filename.
* AssemblyList.assemblies and its lock is now private to the AssemblyList.
* Removed a questionable caching layer (cache was per-AssemblyList, but was caching the result of a per-LoadedAssembly lookup function.
* Replaced static DisableAssemblyLoad() with bool-parameter on GetAssemblyResolver() call.
The assembly list is not automatically sorted into explicit/auto loaded
groups at the moment. Sorting the list loses the tree state (expanded
nodes/selections)...