using System; using System.Collections.Generic; using System.IO; using Mono.Cecil; using Mono.Cecil.Cil; namespace StardewModdingAPI.Framework.ModLoading.Symbols { /// Provides assembly symbol readers for Mono.Cecil. internal class SymbolReaderProvider : ISymbolReaderProvider { /********* ** Fields *********/ /// The underlying symbol reader provider. private readonly ISymbolReaderProvider BaseProvider = new DefaultSymbolReaderProvider(throwIfNoSymbol: false); /// The symbol data loaded by absolute assembly path. private readonly Dictionary SymbolsByAssemblyPath = new(StringComparer.OrdinalIgnoreCase); /********* ** Public methods *********/ /// Add the symbol file for a given assembly name, if it's not already registered. /// The assembly file name. /// Get the raw file stream for the symbols. public void TryAddSymbolData(string fileName, Func getSymbolStream) { if (!this.SymbolsByAssemblyPath.ContainsKey(fileName)) this.SymbolsByAssemblyPath.Add(fileName, getSymbolStream()); } /// Get a symbol reader for a given module and assembly name. /// The loaded assembly module. /// The assembly file name. public ISymbolReader GetSymbolReader(ModuleDefinition module, string fileName) { return this.SymbolsByAssemblyPath.TryGetValue(module.Name, out Stream? symbolData) ? new SymbolReader(module, symbolData) : this.BaseProvider.GetSymbolReader(module, fileName); } /// Get a symbol reader for a given module and symbol stream. /// The loaded assembly module. /// The loaded symbol file stream. public ISymbolReader GetSymbolReader(ModuleDefinition module, Stream symbolStream) { return this.SymbolsByAssemblyPath.TryGetValue(module.Name, out Stream? symbolData) ? new SymbolReader(module, symbolData) : this.BaseProvider.GetSymbolReader(module, symbolStream); } } }