// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.Diagnostics; using System.Threading; using dnlib.DotNet.MD; using dnlib.DotNet.Pdb; namespace dnlib.DotNet { /// /// A high-level representation of a row in the ModuleRef table /// public abstract class ModuleRef : IHasCustomAttribute, IMemberRefParent, IHasCustomDebugInformation, IResolutionScope, IModule, IOwnerModule { /// /// The row id in its table /// protected uint rid; /// /// The owner module /// protected ModuleDef module; /// public MDToken MDToken => new MDToken(Table.ModuleRef, rid); /// public uint Rid { get => rid; set => rid = value; } /// public int HasCustomAttributeTag => 12; /// public int MemberRefParentTag => 2; /// public int ResolutionScopeTag => 1; /// public ScopeType ScopeType => ScopeType.ModuleRef; /// public string ScopeName => FullName; /// /// From column ModuleRef.Name /// public UTF8String Name { get => name; set => name = value; } /// Name protected UTF8String name; /// /// Gets all custom attributes /// public CustomAttributeCollection CustomAttributes { get { if (customAttributes is null) InitializeCustomAttributes(); return customAttributes; } } /// protected CustomAttributeCollection customAttributes; /// Initializes protected virtual void InitializeCustomAttributes() => Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); /// public bool HasCustomAttributes => CustomAttributes.Count > 0; /// public int HasCustomDebugInformationTag => 12; /// public bool HasCustomDebugInfos => CustomDebugInfos.Count > 0; /// /// Gets all custom debug infos /// public IList CustomDebugInfos { get { if (customDebugInfos is null) InitializeCustomDebugInfos(); return customDebugInfos; } } /// protected IList customDebugInfos; /// Initializes protected virtual void InitializeCustomDebugInfos() => Interlocked.CompareExchange(ref customDebugInfos, new List(), null); /// public ModuleDef Module => module; /// /// Gets the definition module, i.e., the module which it references, or null /// if the module can't be found. /// public ModuleDef DefinitionModule { get { if (module is null) return null; var n = name; if (UTF8String.CaseInsensitiveEquals(n, module.Name)) return module; return DefinitionAssembly?.FindModule(n); } } /// /// Gets the definition assembly, i.e., the assembly of the module it references, or /// null if the assembly can't be found. /// public AssemblyDef DefinitionAssembly => module?.Assembly; /// public string FullName => UTF8String.ToSystemStringOrEmpty(name); /// public override string ToString() => FullName; } /// /// A ModuleRef row created by the user and not present in the original .NET file /// public class ModuleRefUser : ModuleRef { /// /// Constructor /// /// Owner module public ModuleRefUser(ModuleDef module) : this(module, UTF8String.Empty) { } /// /// Constructor /// /// Owner module /// Module name public ModuleRefUser(ModuleDef module, UTF8String name) { this.module = module; this.name = name; } } /// /// Created from a row in the ModuleRef table /// sealed class ModuleRefMD : ModuleRef, IMDTokenProviderMD { /// The module where this instance is located readonly ModuleDefMD readerModule; readonly uint origRid; /// public uint OrigRid => origRid; /// protected override void InitializeCustomAttributes() { var list = readerModule.Metadata.GetCustomAttributeRidList(Table.ModuleRef, origRid); var tmp = new CustomAttributeCollection(list.Count, list, (list2, index) => readerModule.ReadCustomAttribute(list[index])); Interlocked.CompareExchange(ref customAttributes, tmp, null); } /// protected override void InitializeCustomDebugInfos() { var list = new List(); readerModule.InitializeCustomDebugInfos(new MDToken(MDToken.Table, origRid), new GenericParamContext(), list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } /// /// Constructor /// /// The module which contains this ModuleRef row /// Row ID /// If is null /// If is invalid public ModuleRefMD(ModuleDefMD readerModule, uint rid) { #if DEBUG if (readerModule is null) throw new ArgumentNullException("readerModule"); if (readerModule.TablesStream.ModuleRefTable.IsInvalidRID(rid)) throw new BadImageFormatException($"ModuleRef rid {rid} does not exist"); #endif origRid = rid; this.rid = rid; this.readerModule = readerModule; module = readerModule; bool b = readerModule.TablesStream.TryReadModuleRefRow(origRid, out var row); Debug.Assert(b); name = readerModule.StringsStream.ReadNoNull(row.Name); } } }