From 942131f4870391b14bced6957151960cdbb73bc1 Mon Sep 17 00:00:00 2001
From: Siegfried Pammer <siegfriedpammer@gmail.com>
Date: Sat, 16 Sep 2023 17:28:50 +0200
Subject: [PATCH 1/5] #3068: Introduce MetadataFile for pure ECMA-335 streams
 and as base class for PEFile

---
 .../Disassembler/DisassemblerHelpers.cs       |   5 +-
 .../DisassemblerSignatureTypeProvider.cs      |   4 +-
 .../Disassembler/IEntityProcessor.cs          |  14 +-
 .../Disassembler/SortByNameProcessor.cs       |  28 +-
 .../IL/InstructionOutputExtensions.cs         |  26 +-
 .../Metadata/MetadataGenericContext.cs        |   2 +-
 ICSharpCode.Decompiler/Metadata/PEFile.cs     |  41 ++-
 ICSharpCode.Decompiler/Output/ITextOutput.cs  |   2 +-
 .../Output/PlainTextOutput.cs                 |   4 +-
 ICSharpCode.ILSpyX/LoadedAssembly.cs          |  85 +++++--
 .../LoadedAssemblyExtensions.cs               |   2 +-
 .../PdbProvider/DebugInfoUtils.cs             |   4 +-
 .../PdbProvider/PortableDebugInfoProvider.cs  |   9 +
 ILSpy/EntityReference.cs                      |   6 +-
 ILSpy/ExtensionMethods.cs                     |   6 +-
 ILSpy/MainWindow.xaml.cs                      |   4 +-
 .../CorTables/AssemblyRefTableTreeNode.cs     |  35 ++-
 .../CorTables/AssemblyTableTreeNode.cs        |  21 +-
 .../CorTables/ClassLayoutTableTreeNode.cs     |  31 +--
 .../CorTables/ConstantTableTreeNode.cs        |  34 +--
 .../CorTables/CustomAttributeTableTreeNode.cs |  38 ++-
 .../CorTables/DeclSecurityTableTreeNode.cs    |  34 +--
 .../CorTables/EventMapTableTreeNode.cs        |  39 ++-
 .../Metadata/CorTables/EventTableTreeNode.cs  |  42 ++-
 .../CorTables/ExportedTypeTableTreeNode.cs    |  35 ++-
 .../CorTables/FieldLayoutTableTreeNode.cs     |  33 +--
 .../CorTables/FieldMarshalTableTreeNode.cs    |  35 ++-
 .../CorTables/FieldRVATableTreeNode.cs        |  32 +--
 .../Metadata/CorTables/FieldTableTreeNode.cs  |  39 ++-
 ILSpy/Metadata/CorTables/FileTableTreeNode.cs |  32 +--
 .../GenericParamConstraintTableTreeNode.cs    |  41 ++-
 .../CorTables/GenericParamTableTreeNode.cs    |  36 ++-
 .../CorTables/ImplMapTableTreeNode.cs         |  43 ++--
 .../CorTables/InterfaceImplTableTreeNode.cs   |  38 ++-
 .../ManifestResourceTableTreeNode.cs          |  36 ++-
 .../CorTables/MemberRefTableTreeNode.cs       |  38 ++-
 .../CorTables/MethodImplTableTreeNode.cs      |  42 ++-
 .../CorTables/MethodSemanticsTableTreeNode.cs |  37 ++-
 .../CorTables/MethodSpecTableTreeNode.cs      |  35 ++-
 .../Metadata/CorTables/MethodTableTreeNode.cs |  43 ++--
 .../CorTables/ModuleRefTableTreeNode.cs       |  30 +--
 .../Metadata/CorTables/ModuleTableTreeNode.cs |  34 ++-
 .../CorTables/NestedClassTableTreeNode.cs     |  37 ++-
 .../Metadata/CorTables/ParamTableTreeNode.cs  |  30 +--
 .../CorTables/PropertyMapTableTreeNode.cs     |  39 ++-
 .../CorTables/PropertyTableTreeNode.cs        |  36 ++-
 .../CorTables/StandAloneSigTableTreeNode.cs   |  32 +--
 .../CorTables/TypeDefTableTreeNode.cs         |  53 ++--
 .../CorTables/TypeRefTableTreeNode.cs         |  37 ++-
 .../CorTables/TypeSpecTableTreeNode.cs        |  20 +-
 ILSpy/Metadata/DebugDirectoryTreeNode.cs      |   6 +-
 ILSpy/Metadata/DebugMetadataTablesTreeNode.cs |  31 +--
 ILSpy/Metadata/DebugMetadataTreeNode.cs       |  24 +-
 .../CustomDebugInformationTableTreeNode.cs    |  44 ++--
 .../DebugTables/DocumentTableTreeNode.cs      |  38 ++-
 .../DebugTables/ImportScopeTableTreeNode.cs   |  39 +--
 .../DebugTables/LocalConstantTableTreeNode.cs |  33 +--
 .../DebugTables/LocalScopeTableTreeNode.cs    |  42 ++-
 .../DebugTables/LocalVariableTableTreeNode.cs |  29 +--
 .../MethodDebugInformationTableTreeNode.cs    |  43 ++--
 .../StateMachineMethodTableTreeNode.cs        |  46 ++--
 ILSpy/Metadata/Heaps/BlobHeapTreeNode.cs      |  16 +-
 ILSpy/Metadata/Heaps/GuidHeapTreeNode.cs      |   6 +-
 ILSpy/Metadata/Heaps/StringHeapTreeNode.cs    |  15 +-
 .../Metadata/Heaps/UserStringHeapTreeNode.cs  |  16 +-
 ILSpy/Metadata/MetadataHeapTreeNode.cs        |  15 +-
 ILSpy/Metadata/MetadataTableTreeNode.cs       |  23 +-
 ILSpy/Metadata/MetadataTablesTreeNode.cs      | 240 ++++++++++++------
 ILSpy/Metadata/MetadataTreeNode.cs            |   8 +-
 ILSpy/TextView/AvalonEditTextOutput.cs        |   6 +-
 ILSpy/TextView/DecompilerTextView.cs          |   3 +-
 71 files changed, 1019 insertions(+), 1163 deletions(-)

diff --git a/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs b/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs
index 89adb046b9..a1d4cc7436 100644
--- a/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs
+++ b/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs
@@ -17,7 +17,6 @@
 // DEALINGS IN THE SOFTWARE.
 
 using System;
-using System.Collections.Generic;
 using System.Linq;
 using System.Reflection.Metadata;
 using System.Text;
@@ -26,8 +25,6 @@
 using ICSharpCode.Decompiler.Metadata;
 using ICSharpCode.Decompiler.Util;
 
-using SRM = System.Reflection.Metadata;
-
 namespace ICSharpCode.Decompiler.Disassembler
 {
 	public enum ILNameSyntax
@@ -72,7 +69,7 @@ public static void WriteOffsetReference(ITextOutput writer, int? offset)
 				writer.WriteLocalReference(OffsetToString(offset.Value), offset);
 		}
 
-		public static void WriteTo(this SRM.ExceptionRegion exceptionHandler, Metadata.PEFile module, MetadataGenericContext context, ITextOutput writer)
+		public static void WriteTo(this ExceptionRegion exceptionHandler, MetadataFile module, MetadataGenericContext context, ITextOutput writer)
 		{
 			writer.Write(".try ");
 			WriteOffsetReference(writer, exceptionHandler.TryOffset);
diff --git a/ICSharpCode.Decompiler/Disassembler/DisassemblerSignatureTypeProvider.cs b/ICSharpCode.Decompiler/Disassembler/DisassemblerSignatureTypeProvider.cs
index 5e09284500..9cfb95fae1 100644
--- a/ICSharpCode.Decompiler/Disassembler/DisassemblerSignatureTypeProvider.cs
+++ b/ICSharpCode.Decompiler/Disassembler/DisassemblerSignatureTypeProvider.cs
@@ -27,11 +27,11 @@ namespace ICSharpCode.Decompiler.Disassembler
 {
 	public class DisassemblerSignatureTypeProvider : ISignatureTypeProvider<Action<ILNameSyntax>, MetadataGenericContext>
 	{
-		readonly PEFile module;
+		readonly MetadataFile module;
 		readonly MetadataReader metadata;
 		readonly ITextOutput output;
 
-		public DisassemblerSignatureTypeProvider(PEFile module, ITextOutput output)
+		public DisassemblerSignatureTypeProvider(MetadataFile module, ITextOutput output)
 		{
 			this.module = module ?? throw new ArgumentNullException(nameof(module));
 			this.output = output ?? throw new ArgumentNullException(nameof(output));
diff --git a/ICSharpCode.Decompiler/Disassembler/IEntityProcessor.cs b/ICSharpCode.Decompiler/Disassembler/IEntityProcessor.cs
index 5d94500d1d..e275dc22ce 100644
--- a/ICSharpCode.Decompiler/Disassembler/IEntityProcessor.cs
+++ b/ICSharpCode.Decompiler/Disassembler/IEntityProcessor.cs
@@ -27,18 +27,18 @@ namespace ICSharpCode.Decompiler.Disassembler
 {
 	public interface IEntityProcessor
 	{
-		IReadOnlyCollection<InterfaceImplementationHandle> Process(PEFile module, IReadOnlyCollection<InterfaceImplementationHandle> items);
+		IReadOnlyCollection<InterfaceImplementationHandle> Process(MetadataFile module, IReadOnlyCollection<InterfaceImplementationHandle> items);
 
-		IReadOnlyCollection<TypeDefinitionHandle> Process(PEFile module, IReadOnlyCollection<TypeDefinitionHandle> items);
+		IReadOnlyCollection<TypeDefinitionHandle> Process(MetadataFile module, IReadOnlyCollection<TypeDefinitionHandle> items);
 
-		IReadOnlyCollection<MethodDefinitionHandle> Process(PEFile module, IReadOnlyCollection<MethodDefinitionHandle> items);
+		IReadOnlyCollection<MethodDefinitionHandle> Process(MetadataFile module, IReadOnlyCollection<MethodDefinitionHandle> items);
 
-		IReadOnlyCollection<PropertyDefinitionHandle> Process(PEFile module, IReadOnlyCollection<PropertyDefinitionHandle> items);
+		IReadOnlyCollection<PropertyDefinitionHandle> Process(MetadataFile module, IReadOnlyCollection<PropertyDefinitionHandle> items);
 
-		IReadOnlyCollection<EventDefinitionHandle> Process(PEFile module, IReadOnlyCollection<EventDefinitionHandle> items);
+		IReadOnlyCollection<EventDefinitionHandle> Process(MetadataFile module, IReadOnlyCollection<EventDefinitionHandle> items);
 
-		IReadOnlyCollection<FieldDefinitionHandle> Process(PEFile module, IReadOnlyCollection<FieldDefinitionHandle> items);
+		IReadOnlyCollection<FieldDefinitionHandle> Process(MetadataFile module, IReadOnlyCollection<FieldDefinitionHandle> items);
 
-		IReadOnlyCollection<CustomAttributeHandle> Process(PEFile module, IReadOnlyCollection<CustomAttributeHandle> items);
+		IReadOnlyCollection<CustomAttributeHandle> Process(MetadataFile module, IReadOnlyCollection<CustomAttributeHandle> items);
 	}
 }
\ No newline at end of file
diff --git a/ICSharpCode.Decompiler/Disassembler/SortByNameProcessor.cs b/ICSharpCode.Decompiler/Disassembler/SortByNameProcessor.cs
index cda178056c..f85e59e61a 100644
--- a/ICSharpCode.Decompiler/Disassembler/SortByNameProcessor.cs
+++ b/ICSharpCode.Decompiler/Disassembler/SortByNameProcessor.cs
@@ -30,52 +30,52 @@ namespace ICSharpCode.Decompiler.Disassembler
 {
 	public class SortByNameProcessor : IEntityProcessor
 	{
-		public IReadOnlyCollection<InterfaceImplementationHandle> Process(PEFile module,
+		public IReadOnlyCollection<InterfaceImplementationHandle> Process(MetadataFile module,
 			IReadOnlyCollection<InterfaceImplementationHandle> items)
 		{
 			return items.OrderBy(item => GetSortKey(item, module)).ToArray();
 		}
 
-		public IReadOnlyCollection<TypeDefinitionHandle> Process(PEFile module,
+		public IReadOnlyCollection<TypeDefinitionHandle> Process(MetadataFile module,
 			IReadOnlyCollection<TypeDefinitionHandle> items)
 		{
 			return items.OrderBy(item => GetSortKey(item, module)).ToArray();
 		}
 
-		public IReadOnlyCollection<MethodDefinitionHandle> Process(PEFile module,
+		public IReadOnlyCollection<MethodDefinitionHandle> Process(MetadataFile module,
 			IReadOnlyCollection<MethodDefinitionHandle> items)
 		{
 			return items.OrderBy(item => GetSortKey(item, module)).ToArray();
 		}
 
-		public IReadOnlyCollection<PropertyDefinitionHandle> Process(PEFile module,
+		public IReadOnlyCollection<PropertyDefinitionHandle> Process(MetadataFile module,
 			IReadOnlyCollection<PropertyDefinitionHandle> items)
 		{
 			return items.OrderBy(item => GetSortKey(item, module)).ToArray();
 		}
 
-		public IReadOnlyCollection<EventDefinitionHandle> Process(PEFile module,
+		public IReadOnlyCollection<EventDefinitionHandle> Process(MetadataFile module,
 			IReadOnlyCollection<EventDefinitionHandle> items)
 		{
 			return items.OrderBy(item => GetSortKey(item, module)).ToArray();
 		}
 
-		public IReadOnlyCollection<FieldDefinitionHandle> Process(PEFile module,
+		public IReadOnlyCollection<FieldDefinitionHandle> Process(MetadataFile module,
 			IReadOnlyCollection<FieldDefinitionHandle> items)
 		{
 			return items.OrderBy(item => GetSortKey(item, module)).ToArray();
 		}
 
-		public IReadOnlyCollection<CustomAttributeHandle> Process(PEFile module,
+		public IReadOnlyCollection<CustomAttributeHandle> Process(MetadataFile module,
 			IReadOnlyCollection<CustomAttributeHandle> items)
 		{
 			return items.OrderBy(item => GetSortKey(item, module)).ToArray();
 		}
 
-		private static string GetSortKey(TypeDefinitionHandle handle, PEFile module) =>
+		private static string GetSortKey(TypeDefinitionHandle handle, MetadataFile module) =>
 			handle.GetFullTypeName(module.Metadata).ToILNameString();
 
-		private static string GetSortKey(MethodDefinitionHandle handle, PEFile module)
+		private static string GetSortKey(MethodDefinitionHandle handle, MetadataFile module)
 		{
 			PlainTextOutput output = new PlainTextOutput();
 			MethodDefinition definition = module.Metadata.GetMethodDefinition(handle);
@@ -97,22 +97,22 @@ private static string GetSortKey(MethodDefinitionHandle handle, PEFile module)
 			return output.ToString();
 		}
 
-		private static string GetSortKey(InterfaceImplementationHandle handle, PEFile module) =>
+		private static string GetSortKey(InterfaceImplementationHandle handle, MetadataFile module) =>
 			module.Metadata.GetInterfaceImplementation(handle)
 				.Interface
 				.GetFullTypeName(module.Metadata)
 				.ToILNameString();
 
-		private static string GetSortKey(FieldDefinitionHandle handle, PEFile module) =>
+		private static string GetSortKey(FieldDefinitionHandle handle, MetadataFile module) =>
 			module.Metadata.GetString(module.Metadata.GetFieldDefinition(handle).Name);
 
-		private static string GetSortKey(PropertyDefinitionHandle handle, PEFile module) =>
+		private static string GetSortKey(PropertyDefinitionHandle handle, MetadataFile module) =>
 			module.Metadata.GetString(module.Metadata.GetPropertyDefinition(handle).Name);
 
-		private static string GetSortKey(EventDefinitionHandle handle, PEFile module) =>
+		private static string GetSortKey(EventDefinitionHandle handle, MetadataFile module) =>
 			module.Metadata.GetString(module.Metadata.GetEventDefinition(handle).Name);
 
-		private static string GetSortKey(CustomAttributeHandle handle, PEFile module) =>
+		private static string GetSortKey(CustomAttributeHandle handle, MetadataFile module) =>
 			module.Metadata.GetCustomAttribute(handle)
 				.Constructor
 				.GetDeclaringType(module.Metadata)
diff --git a/ICSharpCode.Decompiler/IL/InstructionOutputExtensions.cs b/ICSharpCode.Decompiler/IL/InstructionOutputExtensions.cs
index be5ebcd2d7..6c48fa8bd0 100644
--- a/ICSharpCode.Decompiler/IL/InstructionOutputExtensions.cs
+++ b/ICSharpCode.Decompiler/IL/InstructionOutputExtensions.cs
@@ -69,7 +69,7 @@ public static void WriteTo(this Interval interval, ITextOutput output, ILAstWrit
 				output.Write($"[{interval.Start:x4}..{interval.InclusiveEnd:x4}] ");
 		}
 
-		public static void WriteTo(this EntityHandle entity, PEFile module, ITextOutput output, Metadata.MetadataGenericContext genericContext, ILNameSyntax syntax = ILNameSyntax.Signature)
+		public static void WriteTo(this EntityHandle entity, MetadataFile module, ITextOutput output, Metadata.MetadataGenericContext genericContext, ILNameSyntax syntax = ILNameSyntax.Signature)
 		{
 			if (entity.IsNil)
 			{
@@ -138,7 +138,7 @@ public static void WriteTo(this EntityHandle entity, PEFile module, ITextOutput
 				case HandleKind.FieldDefinition:
 				{
 					var fd = metadata.GetFieldDefinition((FieldDefinitionHandle)entity);
-					signature = fd.DecodeSignature(new DisassemblerSignatureTypeProvider(module, output), new Metadata.MetadataGenericContext(fd.GetDeclaringType(), module));
+					signature = fd.DecodeSignature(new DisassemblerSignatureTypeProvider(module, output), new Metadata.MetadataGenericContext(fd.GetDeclaringType(), metadata));
 					signature(ILNameSyntax.SignatureNoNamedTypeParameters);
 					output.Write(' ');
 					((EntityHandle)fd.GetDeclaringType()).WriteTo(module, output, default, ILNameSyntax.TypeName);
@@ -149,7 +149,7 @@ public static void WriteTo(this EntityHandle entity, PEFile module, ITextOutput
 				case HandleKind.MethodDefinition:
 				{
 					var md = metadata.GetMethodDefinition((MethodDefinitionHandle)entity);
-					methodSignature = md.DecodeSignature(new DisassemblerSignatureTypeProvider(module, output), new Metadata.MetadataGenericContext((MethodDefinitionHandle)entity, module));
+					methodSignature = md.DecodeSignature(new DisassemblerSignatureTypeProvider(module, output), new Metadata.MetadataGenericContext((MethodDefinitionHandle)entity, metadata));
 					methodSignature.Header.WriteTo(output);
 					methodSignature.ReturnType(ILNameSyntax.SignatureNoNamedTypeParameters);
 					output.Write(' ');
@@ -198,7 +198,7 @@ public static void WriteTo(this EntityHandle entity, PEFile module, ITextOutput
 									if (j > 0)
 										output.Write(", ");
 									var constraint = metadata.GetGenericParameterConstraint(constraints[j]);
-									constraint.Type.WriteTo(module, output, new Metadata.MetadataGenericContext((MethodDefinitionHandle)entity, module), ILNameSyntax.TypeName);
+									constraint.Type.WriteTo(module, output, new Metadata.MetadataGenericContext((MethodDefinitionHandle)entity, metadata), ILNameSyntax.TypeName);
 								}
 								output.Write(") ");
 							}
@@ -227,7 +227,7 @@ public static void WriteTo(this EntityHandle entity, PEFile module, ITextOutput
 							methodSignature.Header.WriteTo(output);
 							methodSignature.ReturnType(ILNameSyntax.SignatureNoNamedTypeParameters);
 							output.Write(' ');
-							WriteParent(output, module, metadata, mr.Parent, genericContext, syntax);
+							WriteParent(output, module, mr.Parent, genericContext, syntax);
 							output.Write("::");
 							output.WriteReference(module, entity, DisassemblerHelpers.Escape(memberName));
 							WriteParameterList(output, methodSignature);
@@ -236,7 +236,7 @@ public static void WriteTo(this EntityHandle entity, PEFile module, ITextOutput
 							var fieldSignature = mr.DecodeFieldSignature(new DisassemblerSignatureTypeProvider(module, output), genericContext);
 							fieldSignature(ILNameSyntax.SignatureNoNamedTypeParameters);
 							output.Write(' ');
-							WriteParent(output, module, metadata, mr.Parent, genericContext, syntax);
+							WriteParent(output, module, mr.Parent, genericContext, syntax);
 							output.Write("::");
 							output.WriteReference(module, entity, DisassemblerHelpers.Escape(memberName));
 							break;
@@ -279,7 +279,7 @@ public static void WriteTo(this EntityHandle entity, PEFile module, ITextOutput
 							methodSignature.Header.WriteTo(output);
 							methodSignature.ReturnType(ILNameSyntax.SignatureNoNamedTypeParameters);
 							output.Write(' ');
-							WriteParent(output, module, metadata, memberReference.Parent, genericContext, syntax);
+							WriteParent(output, module, memberReference.Parent, genericContext, syntax);
 							output.Write("::");
 							output.Write(DisassemblerHelpers.Escape(memberName));
 							WriteTypeParameterList(output, syntax, substitution);
@@ -352,24 +352,24 @@ internal static void WriteTo(this in SignatureHeader header, ITextOutput output)
 			}
 		}
 
-		static void WriteParent(ITextOutput output, PEFile module, MetadataReader metadata, EntityHandle parentHandle, Metadata.MetadataGenericContext genericContext, ILNameSyntax syntax)
+		static void WriteParent(ITextOutput output, MetadataFile metadataFile, EntityHandle parentHandle, Metadata.MetadataGenericContext genericContext, ILNameSyntax syntax)
 		{
 			switch (parentHandle.Kind)
 			{
 				case HandleKind.MethodDefinition:
-					var methodDef = metadata.GetMethodDefinition((MethodDefinitionHandle)parentHandle);
-					((EntityHandle)methodDef.GetDeclaringType()).WriteTo(module, output, genericContext, syntax);
+					var methodDef = metadataFile.Metadata.GetMethodDefinition((MethodDefinitionHandle)parentHandle);
+					((EntityHandle)methodDef.GetDeclaringType()).WriteTo(metadataFile, output, genericContext, syntax);
 					break;
 				case HandleKind.ModuleReference:
 					output.Write('[');
-					var moduleRef = metadata.GetModuleReference((ModuleReferenceHandle)parentHandle);
-					output.Write(metadata.GetString(moduleRef.Name));
+					var moduleRef = metadataFile.Metadata.GetModuleReference((ModuleReferenceHandle)parentHandle);
+					output.Write(metadataFile.Metadata.GetString(moduleRef.Name));
 					output.Write(']');
 					break;
 				case HandleKind.TypeDefinition:
 				case HandleKind.TypeReference:
 				case HandleKind.TypeSpecification:
-					parentHandle.WriteTo(module, output, genericContext, syntax);
+					parentHandle.WriteTo(metadataFile, output, genericContext, syntax);
 					break;
 			}
 		}
diff --git a/ICSharpCode.Decompiler/Metadata/MetadataGenericContext.cs b/ICSharpCode.Decompiler/Metadata/MetadataGenericContext.cs
index b647579721..44779d0d3a 100644
--- a/ICSharpCode.Decompiler/Metadata/MetadataGenericContext.cs
+++ b/ICSharpCode.Decompiler/Metadata/MetadataGenericContext.cs
@@ -29,7 +29,7 @@ public readonly struct MetadataGenericContext
 		readonly TypeDefinitionHandle declaringType;
 		readonly MethodDefinitionHandle method;
 
-		public MetadataGenericContext(MethodDefinitionHandle method, PEFile module)
+		public MetadataGenericContext(MethodDefinitionHandle method, MetadataFile module)
 		{
 			this.metadata = module.Metadata;
 			this.method = method;
diff --git a/ICSharpCode.Decompiler/Metadata/PEFile.cs b/ICSharpCode.Decompiler/Metadata/PEFile.cs
index 45b72824e9..227053ff9e 100644
--- a/ICSharpCode.Decompiler/Metadata/PEFile.cs
+++ b/ICSharpCode.Decompiler/Metadata/PEFile.cs
@@ -32,6 +32,33 @@
 
 namespace ICSharpCode.Decompiler.Metadata
 {
+	public class MetadataFile
+	{
+		public string FileName { get; }
+		public MetadataReader Metadata { get; }
+
+		public virtual int MetadataOffset { get; }
+		public virtual bool IsEmbedded { get; }
+
+		public MetadataFile(string fileName, MetadataReaderProvider metadata, MetadataReaderOptions metadataOptions = MetadataReaderOptions.Default, int metadataOffset = 0, bool isEmbedded = false)
+		{
+			this.FileName = fileName;
+			this.Metadata = metadata.GetMetadataReader(metadataOptions);
+			this.MetadataOffset = metadataOffset;
+			this.IsEmbedded = isEmbedded;
+		}
+
+		private protected MetadataFile(string fileName, PEReader reader, MetadataReaderOptions metadataOptions = MetadataReaderOptions.Default)
+		{
+			this.FileName = fileName ?? throw new ArgumentNullException(nameof(fileName));
+			_ = reader ?? throw new ArgumentNullException(nameof(reader));
+			if (!reader.HasMetadata)
+				throw new PEFileNotSupportedException("PE file does not contain any managed metadata.");
+			this.Metadata = reader.GetMetadataReader(metadataOptions);
+		}
+	}
+
+
 	/// <summary>
 	/// PEFile is the main class the decompiler uses to represent a metadata assembly/module.
 	/// Every file on disk can be loaded into a standalone PEFile instance.
@@ -46,11 +73,9 @@ namespace ICSharpCode.Decompiler.Metadata
 	/// decompiled type systems.
 	/// </remarks>
 	[DebuggerDisplay("{FileName}")]
-	public class PEFile : IDisposable, TypeSystem.IModuleReference
+	public class PEFile : MetadataFile, IDisposable, TypeSystem.IModuleReference
 	{
-		public string FileName { get; }
 		public PEReader Reader { get; }
-		public MetadataReader Metadata { get; }
 
 		public PEFile(string fileName, PEStreamOptions streamOptions = PEStreamOptions.Default, MetadataReaderOptions metadataOptions = MetadataReaderOptions.Default)
 			: this(fileName, new PEReader(new FileStream(fileName, FileMode.Open, FileAccess.Read), streamOptions), metadataOptions)
@@ -63,16 +88,16 @@ public PEFile(string fileName, Stream stream, PEStreamOptions streamOptions = PE
 		}
 
 		public PEFile(string fileName, PEReader reader, MetadataReaderOptions metadataOptions = MetadataReaderOptions.Default)
+			: base(fileName, reader, metadataOptions)
 		{
-			this.FileName = fileName ?? throw new ArgumentNullException(nameof(fileName));
-			this.Reader = reader ?? throw new ArgumentNullException(nameof(reader));
-			if (!reader.HasMetadata)
-				throw new PEFileNotSupportedException("PE file does not contain any managed metadata.");
-			this.Metadata = reader.GetMetadataReader(metadataOptions);
+			this.Reader = reader;
 		}
 
 		public bool IsAssembly => Metadata.IsAssembly;
 
+		public override bool IsEmbedded => false;
+		public override int MetadataOffset => Reader.PEHeaders.MetadataStartOffset;
+
 		string? name;
 
 		public string Name {
diff --git a/ICSharpCode.Decompiler/Output/ITextOutput.cs b/ICSharpCode.Decompiler/Output/ITextOutput.cs
index c099df6092..db896fa863 100644
--- a/ICSharpCode.Decompiler/Output/ITextOutput.cs
+++ b/ICSharpCode.Decompiler/Output/ITextOutput.cs
@@ -34,7 +34,7 @@ public interface ITextOutput
 		void Write(string text);
 		void WriteLine();
 		void WriteReference(OpCodeInfo opCode, bool omitSuffix = false);
-		void WriteReference(PEFile module, Handle handle, string text, string protocol = "decompile", bool isDefinition = false);
+		void WriteReference(MetadataFile metadata, Handle handle, string text, string protocol = "decompile", bool isDefinition = false);
 		void WriteReference(IType type, string text, bool isDefinition = false);
 		void WriteReference(IMember member, string text, bool isDefinition = false);
 		void WriteLocalReference(string text, object reference, bool isDefinition = false);
diff --git a/ICSharpCode.Decompiler/Output/PlainTextOutput.cs b/ICSharpCode.Decompiler/Output/PlainTextOutput.cs
index 4daff8ffd9..2af592b931 100644
--- a/ICSharpCode.Decompiler/Output/PlainTextOutput.cs
+++ b/ICSharpCode.Decompiler/Output/PlainTextOutput.cs
@@ -123,7 +123,7 @@ public void WriteReference(Disassembler.OpCodeInfo opCode, bool omitSuffix = fal
 			}
 		}
 
-		public void WriteReference(PEFile module, Handle handle, string text, string protocol = "decompile", bool isDefinition = false)
+		public void WriteReference(MetadataFile module, Handle handle, string text, string protocol = "decompile", bool isDefinition = false)
 		{
 			Write(text);
 		}
@@ -225,7 +225,7 @@ public void WriteReference(OpCodeInfo opCode, bool omitSuffix = false)
 			actions.Add(target => target.WriteReference(opCode));
 		}
 
-		public void WriteReference(PEFile module, Handle handle, string text, string protocol = "decompile", bool isDefinition = false)
+		public void WriteReference(MetadataFile module, Handle handle, string text, string protocol = "decompile", bool isDefinition = false)
 		{
 			actions.Add(target => target.WriteReference(module, handle, text, protocol, isDefinition));
 		}
diff --git a/ICSharpCode.ILSpyX/LoadedAssembly.cs b/ICSharpCode.ILSpyX/LoadedAssembly.cs
index 5ca6529495..feda8088fd 100644
--- a/ICSharpCode.ILSpyX/LoadedAssembly.cs
+++ b/ICSharpCode.ILSpyX/LoadedAssembly.cs
@@ -50,32 +50,39 @@ namespace ICSharpCode.ILSpyX
 	///   * a non-existant file
 	///   * a file of unknown format that could not be loaded
 	///   * a .nupkg file or .NET core bundle
+	///   * a standalone portable pdb file or metadata stream
 	///   * a file that is still being loaded in the background
 	/// </summary>
 	[DebuggerDisplay("[LoadedAssembly {shortName}]")]
 	public sealed class LoadedAssembly
 	{
 		/// <summary>
-		/// Maps from PEFile (successfully loaded .NET module) back to the LoadedAssembly instance
+		/// Maps from MetadataFile (successfully loaded .NET module) back to the LoadedAssembly instance
 		/// that was used to load the module.
 		/// </summary>
-		internal static readonly ConditionalWeakTable<PEFile, LoadedAssembly> loadedAssemblies = new ConditionalWeakTable<PEFile, LoadedAssembly>();
+		internal static readonly ConditionalWeakTable<MetadataFile, LoadedAssembly> loadedAssemblies = new ConditionalWeakTable<MetadataFile, LoadedAssembly>();
 
 		public sealed class LoadResult
 		{
-			public PEFile? PEFile { get; }
-			public Exception? PEFileLoadException { get; }
+			public MetadataFile? MetadataFile { get; }
+			public PEFile? PEFile => MetadataFile as PEFile;
+			public Exception? FileLoadException { get; }
 			public LoadedPackage? Package { get; }
 
 			public LoadResult(PEFile peFile)
 			{
-				this.PEFile = peFile ?? throw new ArgumentNullException(nameof(peFile));
+				this.MetadataFile = peFile ?? throw new ArgumentNullException(nameof(peFile));
 			}
-			public LoadResult(Exception peFileLoadException, LoadedPackage package)
+			public LoadResult(Exception fileLoadException, LoadedPackage package)
 			{
-				this.PEFileLoadException = peFileLoadException ?? throw new ArgumentNullException(nameof(peFileLoadException));
+				this.FileLoadException = fileLoadException ?? throw new ArgumentNullException(nameof(fileLoadException));
 				this.Package = package ?? throw new ArgumentNullException(nameof(package));
 			}
+			public LoadResult(Exception fileLoadException, MetadataFile metadataFile)
+			{
+				this.FileLoadException = fileLoadException ?? throw new ArgumentNullException(nameof(fileLoadException));
+				this.MetadataFile = metadataFile ?? throw new ArgumentNullException(nameof(metadataFile));
+			}
 		}
 
 		readonly Task<LoadResult> loadingTask;
@@ -170,7 +177,7 @@ public async Task<PEFile> GetPEFileAsync()
 			if (loadResult.PEFile != null)
 				return loadResult.PEFile;
 			else
-				throw loadResult.PEFileLoadException!;
+				throw loadResult.FileLoadException!;
 		}
 
 		/// <summary>
@@ -260,31 +267,35 @@ public string Text {
 			get {
 				if (IsLoaded && !HasLoadError)
 				{
-					PEFile? module = GetPEFileOrNull();
-					var metadata = module?.Metadata;
-					string? versionOrInfo = null;
-					if (metadata != null)
+					var result = GetLoadResultAsync().GetAwaiter().GetResult();
+					if (result.PEFile != null)
 					{
-						if (metadata.IsAssembly)
-						{
-							versionOrInfo = metadata.GetAssemblyDefinition().Version?.ToString();
-							string tfId = GetTargetFrameworkIdAsync().GetAwaiter().GetResult();
-							if (!string.IsNullOrEmpty(tfId))
-								versionOrInfo += ", " + tfId.Replace("Version=", " ");
-						}
-						else
+						var metadata = result.PEFile.Metadata;
+						string? versionOrInfo = null;
+						if (metadata != null)
 						{
-							versionOrInfo = ".netmodule";
+							if (metadata.IsAssembly)
+							{
+								versionOrInfo = metadata.GetAssemblyDefinition().Version?.ToString();
+								string tfId = GetTargetFrameworkIdAsync().GetAwaiter().GetResult();
+								if (!string.IsNullOrEmpty(tfId))
+									versionOrInfo += ", " + tfId.Replace("Version=", " ");
+							}
+							else
+							{
+								versionOrInfo = ".netmodule";
+							}
 						}
+						if (versionOrInfo == null)
+							return ShortName;
+						return string.Format("{0} ({1})", ShortName, versionOrInfo);
+					}
+					else if (result.MetadataFile != null)
+					{
+						return ShortName + " (Metadata)";
 					}
-					if (versionOrInfo == null)
-						return ShortName;
-					return string.Format("{0} ({1})", ShortName, versionOrInfo);
-				}
-				else
-				{
-					return ShortName;
 				}
+				return ShortName;
 			}
 		}
 
@@ -374,6 +385,24 @@ async Task<LoadResult> LoadAsync(Task<Stream?>? streamTask)
 				return new LoadResult(loadAssemblyException, zip);
 			}
 			catch (InvalidDataException)
+			{
+				// Not a compressed module, try other options below
+			}
+			// or it could be a standalone portable PDB
+			try
+			{
+				using (var fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
+				{
+					var metadata = MetadataReaderProvider.FromMetadataStream(fileStream, MetadataStreamOptions.PrefetchMetadata);
+					var metadataFile = new MetadataFile(fileName, metadata);
+					lock (loadedAssemblies)
+					{
+						loadedAssemblies.Add(metadataFile, this);
+					}
+					return new LoadResult(loadAssemblyException, metadataFile);
+				}
+			}
+			catch (Exception)
 			{
 				throw loadAssemblyException;
 			}
diff --git a/ICSharpCode.ILSpyX/LoadedAssemblyExtensions.cs b/ICSharpCode.ILSpyX/LoadedAssemblyExtensions.cs
index 8fe549b28b..d35c6c752a 100644
--- a/ICSharpCode.ILSpyX/LoadedAssemblyExtensions.cs
+++ b/ICSharpCode.ILSpyX/LoadedAssemblyExtensions.cs
@@ -52,7 +52,7 @@ internal static IAssemblyResolver GetAssemblyResolver(this PEFile file, Assembly
 			return GetLoadedAssembly(file).GetTypeSystemOrNull(DecompilerTypeSystem.GetOptions(settings));
 		}
 
-		public static LoadedAssembly GetLoadedAssembly(this PEFile file)
+		public static LoadedAssembly GetLoadedAssembly(this MetadataFile file)
 		{
 			if (file == null)
 				throw new ArgumentNullException(nameof(file));
diff --git a/ICSharpCode.ILSpyX/PdbProvider/DebugInfoUtils.cs b/ICSharpCode.ILSpyX/PdbProvider/DebugInfoUtils.cs
index cf1cca9130..d01257876f 100644
--- a/ICSharpCode.ILSpyX/PdbProvider/DebugInfoUtils.cs
+++ b/ICSharpCode.ILSpyX/PdbProvider/DebugInfoUtils.cs
@@ -39,7 +39,7 @@ public static class DebugInfoUtils
 				// try to open portable pdb file/embedded pdb info:
 				if (TryOpenPortablePdb(module, out var provider, out var pdbFileName))
 				{
-					return new PortableDebugInfoProvider(module.FileName, provider, pdbFileName);
+					return new PortableDebugInfoProvider(module.FileName, provider, MetadataReaderOptions.Default, pdbFileName);
 				}
 				else
 				{
@@ -80,7 +80,7 @@ public static class DebugInfoUtils
 			{
 				stream.Position = 0;
 				var provider = MetadataReaderProvider.FromPortablePdbStream(stream);
-				return new PortableDebugInfoProvider(module.FileName, provider, pdbFileName);
+				return new PortableDebugInfoProvider(module.FileName, provider, MetadataReaderOptions.Default, pdbFileName);
 			}
 		}
 
diff --git a/ICSharpCode.ILSpyX/PdbProvider/PortableDebugInfoProvider.cs b/ICSharpCode.ILSpyX/PdbProvider/PortableDebugInfoProvider.cs
index 5cacbbe6dc..32583ed626 100644
--- a/ICSharpCode.ILSpyX/PdbProvider/PortableDebugInfoProvider.cs
+++ b/ICSharpCode.ILSpyX/PdbProvider/PortableDebugInfoProvider.cs
@@ -23,6 +23,7 @@
 using System.Reflection.Metadata;
 
 using ICSharpCode.Decompiler.DebugInfo;
+using ICSharpCode.Decompiler.Metadata;
 using ICSharpCode.Decompiler.Util;
 
 #nullable enable
@@ -34,15 +35,18 @@ class PortableDebugInfoProvider : IDebugInfoProvider
 		string? pdbFileName;
 		string moduleFileName;
 		readonly MetadataReaderProvider provider;
+		MetadataReaderOptions options;
 		bool hasError;
 
 		internal bool IsEmbedded => pdbFileName == null;
 
 		public PortableDebugInfoProvider(string moduleFileName, MetadataReaderProvider provider,
+			MetadataReaderOptions options = MetadataReaderOptions.Default,
 			string? pdbFileName = null)
 		{
 			this.moduleFileName = moduleFileName ?? throw new ArgumentNullException(nameof(moduleFileName));
 			this.provider = provider ?? throw new ArgumentNullException(nameof(provider));
+			this.options = options;
 			this.pdbFileName = pdbFileName;
 		}
 
@@ -233,5 +237,10 @@ public bool TryGetExtraTypeInfo(MethodDefinitionHandle method, int index, out Pd
 
 			return extraTypeInfo.TupleElementNames != null || extraTypeInfo.DynamicFlags != null;
 		}
+
+		public MetadataFile ToMetadataFile()
+		{
+			return new MetadataFile(SourceFileName, provider, options, 0, IsEmbedded);
+		}
 	}
 }
diff --git a/ILSpy/EntityReference.cs b/ILSpy/EntityReference.cs
index 86ebd55a29..d74448aa58 100644
--- a/ILSpy/EntityReference.cs
+++ b/ILSpy/EntityReference.cs
@@ -28,7 +28,7 @@ namespace ICSharpCode.ILSpy
 	[DebuggerDisplay("EntityReference Module={Module}, Handle={Handle}, Protocol={Protocol}")]
 	public class EntityReference
 	{
-		readonly PEFile? peFile;
+		readonly MetadataFile? peFile;
 		public string Module { get; }
 		public Handle Handle { get; }
 		public string Protocol { get; }
@@ -46,7 +46,7 @@ public EntityReference(string? protocol, string moduleFileName, Handle handle)
 			this.Protocol = protocol ?? "decompile";
 		}
 
-		public EntityReference(PEFile module, Handle handle, string protocol = "decompile")
+		public EntityReference(MetadataFile module, Handle handle, string protocol = "decompile")
 		{
 			this.peFile = module;
 			this.Module = module.FileName;
@@ -54,7 +54,7 @@ public EntityReference(PEFile module, Handle handle, string protocol = "decompil
 			this.Protocol = protocol;
 		}
 
-		public PEFile? ResolveAssembly(AssemblyList context)
+		public MetadataFile? ResolveAssembly(AssemblyList context)
 		{
 			return peFile ?? context.FindAssembly(Module)?.GetPEFileOrNull();
 		}
diff --git a/ILSpy/ExtensionMethods.cs b/ILSpy/ExtensionMethods.cs
index f08fc8e117..68c604a0d6 100644
--- a/ILSpy/ExtensionMethods.cs
+++ b/ILSpy/ExtensionMethods.cs
@@ -19,17 +19,13 @@
 #nullable enable
 
 using System;
-using System.Collections;
 using System.Collections.Generic;
-using System.Linq;
 using System.Windows;
 using System.Windows.Controls;
 using System.Windows.Media;
 
 using ICSharpCode.Decompiler.Metadata;
 using ICSharpCode.Decompiler.TypeSystem;
-using ICSharpCode.Decompiler.Util;
-using ICSharpCode.ILSpy.Options;
 using ICSharpCode.ILSpyX;
 
 namespace ICSharpCode.ILSpy
@@ -76,7 +72,7 @@ public static U[] SelectArray<T, U>(this ICollection<T> collection, Func<T, U> f
 			return result;
 		}
 
-		public static ICompilation? GetTypeSystemWithCurrentOptionsOrNull(this PEFile file)
+		public static ICompilation? GetTypeSystemWithCurrentOptionsOrNull(this MetadataFile file)
 		{
 			return LoadedAssemblyExtensions.GetLoadedAssembly(file)
 				.GetTypeSystemOrNull(DecompilerTypeSystem.GetOptions(MainWindow.Instance.CurrentDecompilerSettings));
diff --git a/ILSpy/MainWindow.xaml.cs b/ILSpy/MainWindow.xaml.cs
index c31d35affe..6f31ea9e54 100644
--- a/ILSpy/MainWindow.xaml.cs
+++ b/ILSpy/MainWindow.xaml.cs
@@ -1307,7 +1307,7 @@ public Task JumpToReferenceAsync(object reference, bool inNewTabPage)
 					break;
 				case EntityReference unresolvedEntity:
 					string protocol = unresolvedEntity.Protocol ?? "decompile";
-					PEFile file = unresolvedEntity.ResolveAssembly(assemblyList);
+					PEFile file = unresolvedEntity.ResolveAssembly(assemblyList) as PEFile;
 					if (file == null)
 					{
 						break;
@@ -1378,7 +1378,7 @@ void OpenCommandExecuted(object sender, ExecutedRoutedEventArgs e)
 		{
 			e.Handled = true;
 			OpenFileDialog dlg = new OpenFileDialog();
-			dlg.Filter = ".NET assemblies|*.dll;*.exe;*.winmd|Nuget Packages (*.nupkg)|*.nupkg|All files|*.*";
+			dlg.Filter = ".NET assemblies|*.dll;*.exe;*.winmd|Nuget Packages (*.nupkg)|*.nupkg|Portable Program Database (*.pdb)|*.pdb|All files|*.*";
 			dlg.Multiselect = true;
 			dlg.RestoreDirectory = true;
 			if (dlg.ShowDialog() == true)
diff --git a/ILSpy/Metadata/CorTables/AssemblyRefTableTreeNode.cs b/ILSpy/Metadata/CorTables/AssemblyRefTableTreeNode.cs
index 4ad56815d7..41dff502c2 100644
--- a/ILSpy/Metadata/CorTables/AssemblyRefTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/AssemblyRefTableTreeNode.cs
@@ -29,12 +29,12 @@ namespace ICSharpCode.ILSpy.Metadata
 {
 	internal class AssemblyRefTableTreeNode : MetadataTableTreeNode
 	{
-		public AssemblyRefTableTreeNode(PEFile module)
-			: base(HandleKind.AssemblyReference, module)
+		public AssemblyRefTableTreeNode(MetadataFile metadataFile)
+			: base(HandleKind.AssemblyReference, metadataFile)
 		{
 		}
 
-		public override object Text => $"23 AssemblyRef ({module.Metadata.GetTableRowCount(TableIndex.AssemblyRef)})";
+		public override object Text => $"23 AssemblyRef ({metadataFile.Metadata.GetTableRowCount(TableIndex.AssemblyRef)})";
 
 		public override object Icon => Images.Literal;
 
@@ -44,13 +44,12 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			tabPage.SupportsLanguageSwitching = false;
 
 			var view = Helpers.PrepareDataGrid(tabPage, this);
-			var metadata = module.Metadata;
 			var list = new List<AssemblyRefEntry>();
 			AssemblyRefEntry scrollTargetEntry = default;
 
-			foreach (var row in metadata.AssemblyReferences)
+			foreach (var row in metadataFile.Metadata.AssemblyReferences)
 			{
-				AssemblyRefEntry entry = new AssemblyRefEntry(module, row);
+				AssemblyRefEntry entry = new AssemblyRefEntry(metadataFile, row);
 				if (scrollTarget == MetadataTokens.GetRowNumber(row))
 				{
 					scrollTargetEntry = entry;
@@ -71,9 +70,7 @@ public override bool View(ViewModels.TabPageModel tabPage)
 
 		struct AssemblyRefEntry
 		{
-			readonly int metadataOffset;
-			readonly PEFile module;
-			readonly MetadataReader metadata;
+			readonly MetadataFile metadataFile;
 			readonly AssemblyReferenceHandle handle;
 			readonly System.Reflection.Metadata.AssemblyReference assemblyRef;
 
@@ -81,9 +78,9 @@ struct AssemblyRefEntry
 
 			public int Token => MetadataTokens.GetToken(handle);
 
-			public int Offset => metadataOffset
-				+ metadata.GetTableMetadataOffset(TableIndex.AssemblyRef)
-				+ metadata.GetTableRowSize(TableIndex.AssemblyRef) * (RID - 1);
+			public int Offset => metadataFile.MetadataOffset
+				+ metadataFile.Metadata.GetTableMetadataOffset(TableIndex.AssemblyRef)
+				+ metadataFile.Metadata.GetTableRowSize(TableIndex.AssemblyRef) * (RID - 1);
 
 			public Version Version => assemblyRef.Version;
 
@@ -101,26 +98,24 @@ public string PublicKeyOrTokenTooltip {
 				get {
 					if (assemblyRef.PublicKeyOrToken.IsNil)
 						return null;
-					System.Collections.Immutable.ImmutableArray<byte> token = metadata.GetBlobContent(assemblyRef.PublicKeyOrToken);
+					System.Collections.Immutable.ImmutableArray<byte> token = metadataFile.Metadata.GetBlobContent(assemblyRef.PublicKeyOrToken);
 					return token.ToHexString(token.Length);
 				}
 			}
 
 			public string NameTooltip => $"{MetadataTokens.GetHeapOffset(assemblyRef.Name):X} \"{Name}\"";
 
-			public string Name => metadata.GetString(assemblyRef.Name);
+			public string Name => metadataFile.Metadata.GetString(assemblyRef.Name);
 
 			public string CultureTooltip => $"{MetadataTokens.GetHeapOffset(assemblyRef.Culture):X} \"{Culture}\"";
 
-			public string Culture => metadata.GetString(assemblyRef.Culture);
+			public string Culture => metadataFile.Metadata.GetString(assemblyRef.Culture);
 
-			public AssemblyRefEntry(PEFile module, AssemblyReferenceHandle handle)
+			public AssemblyRefEntry(MetadataFile metadataFile, AssemblyReferenceHandle handle)
 			{
-				this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
-				this.module = module;
-				this.metadata = module.Metadata;
+				this.metadataFile = metadataFile;
 				this.handle = handle;
-				this.assemblyRef = metadata.GetAssemblyReference(handle);
+				this.assemblyRef = metadataFile.Metadata.GetAssemblyReference(handle);
 			}
 		}
 
diff --git a/ILSpy/Metadata/CorTables/AssemblyTableTreeNode.cs b/ILSpy/Metadata/CorTables/AssemblyTableTreeNode.cs
index 5d8409657d..b12c8cf3cc 100644
--- a/ILSpy/Metadata/CorTables/AssemblyTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/AssemblyTableTreeNode.cs
@@ -17,7 +17,6 @@
 // DEALINGS IN THE SOFTWARE.
 
 using System;
-using System.Collections.Generic;
 using System.Reflection;
 using System.Reflection.Metadata;
 using System.Reflection.Metadata.Ecma335;
@@ -29,12 +28,12 @@ namespace ICSharpCode.ILSpy.Metadata
 {
 	internal class AssemblyTableTreeNode : MetadataTableTreeNode
 	{
-		public AssemblyTableTreeNode(PEFile module)
-			: base(HandleKind.AssemblyDefinition, module)
+		public AssemblyTableTreeNode(MetadataFile metadataFile)
+			: base(HandleKind.AssemblyDefinition, metadataFile)
 		{
 		}
 
-		public override object Text => $"20 Assembly ({module.Metadata.GetTableRowCount(TableIndex.Assembly)})";
+		public override object Text => $"20 Assembly ({metadataFile.Metadata.GetTableRowCount(TableIndex.Assembly)})";
 
 		public override object Icon => Images.Literal;
 
@@ -44,9 +43,9 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			tabPage.SupportsLanguageSwitching = false;
 
 			var view = Helpers.PrepareDataGrid(tabPage, this);
-			if (module.IsAssembly)
+			if (metadataFile.Metadata.IsAssembly)
 			{
-				view.ItemsSource = new[] { new AssemblyEntry(module) };
+				view.ItemsSource = new[] { new AssemblyEntry(metadataFile.Metadata, metadataFile.MetadataOffset) };
 			}
 			else
 			{
@@ -57,10 +56,9 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			return true;
 		}
 
-		struct AssemblyEntry
+		readonly struct AssemblyEntry
 		{
 			readonly int metadataOffset;
-			readonly PEFile module;
 			readonly MetadataReader metadata;
 			readonly AssemblyDefinition assembly;
 
@@ -96,11 +94,10 @@ struct AssemblyEntry
 
 			public string Culture => metadata.GetString(assembly.Culture);
 
-			public AssemblyEntry(PEFile module)
+			public AssemblyEntry(MetadataReader metadata, int metadataOffset)
 			{
-				this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
-				this.module = module;
-				this.metadata = module.Metadata;
+				this.metadata = metadata;
+				this.metadataOffset = metadataOffset;
 				this.assembly = metadata.GetAssemblyDefinition();
 			}
 		}
diff --git a/ILSpy/Metadata/CorTables/ClassLayoutTableTreeNode.cs b/ILSpy/Metadata/CorTables/ClassLayoutTableTreeNode.cs
index bc939f1bca..a7191f2023 100644
--- a/ILSpy/Metadata/CorTables/ClassLayoutTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/ClassLayoutTableTreeNode.cs
@@ -23,20 +23,18 @@
 using System.Reflection.Metadata.Ecma335;
 
 using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.Disassembler;
-using ICSharpCode.Decompiler.IL;
 using ICSharpCode.Decompiler.Metadata;
 
 namespace ICSharpCode.ILSpy.Metadata
 {
 	class ClassLayoutTableTreeNode : MetadataTableTreeNode
 	{
-		public ClassLayoutTableTreeNode(PEFile module)
-			: base((HandleKind)0x0F, module)
+		public ClassLayoutTableTreeNode(MetadataFile metadataFile)
+			: base((HandleKind)0x0F, metadataFile)
 		{
 		}
 
-		public override object Text => $"0F ClassLayout ({module.Metadata.GetTableRowCount(TableIndex.ClassLayout)})";
+		public override object Text => $"0F ClassLayout ({metadataFile.Metadata.GetTableRowCount(TableIndex.ClassLayout)})";
 
 		public override object Icon => Images.Literal;
 
@@ -46,18 +44,16 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			tabPage.SupportsLanguageSwitching = false;
 
 			var view = Helpers.PrepareDataGrid(tabPage, this);
-			var metadata = module.Metadata;
 
 			var list = new List<ClassLayoutEntry>();
 
-			var length = metadata.GetTableRowCount(TableIndex.ClassLayout);
-			ReadOnlySpan<byte> ptr = metadata.AsReadOnlySpan();
-			int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
+			var length = metadataFile.Metadata.GetTableRowCount(TableIndex.ClassLayout);
+			ReadOnlySpan<byte> ptr = metadataFile.Metadata.AsReadOnlySpan();
 			ClassLayoutEntry scrollTargetEntry = default;
 
 			for (int rid = 1; rid <= length; rid++)
 			{
-				ClassLayoutEntry entry = new ClassLayoutEntry(module, ptr, metadataOffset, rid);
+				ClassLayoutEntry entry = new ClassLayoutEntry(metadataFile, ptr, rid);
 				if (scrollTarget == rid)
 				{
 					scrollTargetEntry = entry;
@@ -92,8 +88,7 @@ public ClassLayout(ReadOnlySpan<byte> ptr, int typeDefSize)
 
 		struct ClassLayoutEntry
 		{
-			readonly PEFile module;
-			readonly MetadataReader metadata;
+			readonly MetadataFile metadataFile;
 			readonly ClassLayout classLayout;
 
 			public int RID { get; }
@@ -107,11 +102,11 @@ struct ClassLayoutEntry
 
 			public void OnParentClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, classLayout.Parent, protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference("metadata", classLayout.Parent));
 			}
 
 			string parentTooltip;
-			public string ParentTooltip => GenerateTooltip(ref parentTooltip, module, classLayout.Parent);
+			public string ParentTooltip => GenerateTooltip(ref parentTooltip, metadataFile, classLayout.Parent);
 
 			[ColumnInfo("X4", Kind = ColumnKind.Other)]
 			public ushort PackingSize => classLayout.PackingSize;
@@ -119,14 +114,14 @@ public void OnParentClick()
 			[ColumnInfo("X8", Kind = ColumnKind.Other)]
 			public uint ClassSize => classLayout.ClassSize;
 
-			public ClassLayoutEntry(PEFile module, ReadOnlySpan<byte> ptr, int metadataOffset, int row)
+			public ClassLayoutEntry(MetadataFile metadataFile, ReadOnlySpan<byte> ptr, int row)
 			{
-				this.module = module;
-				this.metadata = module.Metadata;
+				this.metadataFile = metadataFile;
 				this.RID = row;
+				var metadata = metadataFile.Metadata;
 				var rowOffset = metadata.GetTableMetadataOffset(TableIndex.ClassLayout)
 					+ metadata.GetTableRowSize(TableIndex.ClassLayout) * (row - 1);
-				this.Offset = metadataOffset + rowOffset;
+				this.Offset = metadataFile.MetadataOffset + rowOffset;
 				this.classLayout = new ClassLayout(ptr.Slice(rowOffset), metadata.GetTableRowCount(TableIndex.TypeDef) < ushort.MaxValue ? 2 : 4);
 				this.parentTooltip = null;
 			}
diff --git a/ILSpy/Metadata/CorTables/ConstantTableTreeNode.cs b/ILSpy/Metadata/CorTables/ConstantTableTreeNode.cs
index 3f9dc97c8a..dd45da5af3 100644
--- a/ILSpy/Metadata/CorTables/ConstantTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/ConstantTableTreeNode.cs
@@ -21,8 +21,6 @@
 using System.Reflection.Metadata.Ecma335;
 
 using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.Disassembler;
-using ICSharpCode.Decompiler.IL;
 using ICSharpCode.Decompiler.Metadata;
 using ICSharpCode.ILSpy.ViewModels;
 
@@ -30,12 +28,12 @@ namespace ICSharpCode.ILSpy.Metadata
 {
 	internal class ConstantTableTreeNode : MetadataTableTreeNode
 	{
-		public ConstantTableTreeNode(PEFile module)
-			: base((HandleKind)0x0B, module)
+		public ConstantTableTreeNode(MetadataFile metadataFile)
+			: base((HandleKind)0x0B, metadataFile)
 		{
 		}
 
-		public override object Text => $"0B Constant ({module.Metadata.GetTableRowCount(TableIndex.Constant)})";
+		public override object Text => $"0B Constant ({metadataFile.Metadata.GetTableRowCount(TableIndex.Constant)})";
 
 		public override object Icon => Images.Literal;
 
@@ -45,14 +43,14 @@ public override bool View(TabPageModel tabPage)
 			tabPage.SupportsLanguageSwitching = false;
 
 			var view = Helpers.PrepareDataGrid(tabPage, this);
-			var metadata = module.Metadata;
+			var metadata = metadataFile.Metadata;
 
 			var list = new List<ConstantEntry>();
 			ConstantEntry scrollTargetEntry = default;
 
 			for (int row = 1; row <= metadata.GetTableRowCount(TableIndex.Constant); row++)
 			{
-				ConstantEntry entry = new ConstantEntry(module, MetadataTokens.ConstantHandle(row));
+				ConstantEntry entry = new ConstantEntry(metadataFile, MetadataTokens.ConstantHandle(row));
 				if (scrollTarget == row)
 				{
 					scrollTargetEntry = entry;
@@ -73,9 +71,7 @@ public override bool View(TabPageModel tabPage)
 
 		struct ConstantEntry
 		{
-			readonly int metadataOffset;
-			readonly PEFile module;
-			readonly MetadataReader metadata;
+			readonly MetadataFile metadataFile;
 			readonly EntityHandle handle;
 			readonly Constant constant;
 
@@ -83,9 +79,9 @@ struct ConstantEntry
 
 			public int Token => MetadataTokens.GetToken(handle);
 
-			public int Offset => metadataOffset
-				+ metadata.GetTableMetadataOffset(TableIndex.Constant)
-				+ metadata.GetTableRowSize(TableIndex.Constant) * (RID - 1);
+			public int Offset => metadataFile.MetadataOffset
+				+ metadataFile.Metadata.GetTableMetadataOffset(TableIndex.Constant)
+				+ metadataFile.Metadata.GetTableRowSize(TableIndex.Constant) * (RID - 1);
 
 			[ColumnInfo("X8", Kind = ColumnKind.Other)]
 			public ConstantTypeCode Type => constant.TypeCode;
@@ -97,11 +93,11 @@ struct ConstantEntry
 
 			public void OnParentClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, constant.Parent, protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, constant.Parent, protocol: "metadata"));
 			}
 
 			string parentTooltip;
-			public string ParentTooltip => GenerateTooltip(ref parentTooltip, module, constant.Parent);
+			public string ParentTooltip => GenerateTooltip(ref parentTooltip, metadataFile, constant.Parent);
 
 			[ColumnInfo("X8", Kind = ColumnKind.HeapOffset)]
 			public int Value => MetadataTokens.GetHeapOffset(constant.Value);
@@ -112,13 +108,11 @@ public string ValueTooltip {
 				}
 			}
 
-			public ConstantEntry(PEFile module, ConstantHandle handle)
+			public ConstantEntry(MetadataFile metadataFile, ConstantHandle handle)
 			{
-				this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
-				this.module = module;
-				this.metadata = module.Metadata;
+				this.metadataFile = metadataFile;
 				this.handle = handle;
-				this.constant = metadata.GetConstant(handle);
+				this.constant = metadataFile.Metadata.GetConstant(handle);
 				this.parentTooltip = null;
 			}
 		}
diff --git a/ILSpy/Metadata/CorTables/CustomAttributeTableTreeNode.cs b/ILSpy/Metadata/CorTables/CustomAttributeTableTreeNode.cs
index 30a6cf47f0..976a013628 100644
--- a/ILSpy/Metadata/CorTables/CustomAttributeTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/CustomAttributeTableTreeNode.cs
@@ -21,20 +21,18 @@
 using System.Reflection.Metadata.Ecma335;
 
 using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.Disassembler;
-using ICSharpCode.Decompiler.IL;
 using ICSharpCode.Decompiler.Metadata;
 
 namespace ICSharpCode.ILSpy.Metadata
 {
 	class CustomAttributeTableTreeNode : MetadataTableTreeNode
 	{
-		public CustomAttributeTableTreeNode(PEFile module)
-			: base(HandleKind.CustomAttribute, module)
+		public CustomAttributeTableTreeNode(MetadataFile metadataFile)
+			: base(HandleKind.CustomAttribute, metadataFile)
 		{
 		}
 
-		public override object Text => $"0C CustomAttribute ({module.Metadata.GetTableRowCount(TableIndex.CustomAttribute)})";
+		public override object Text => $"0C CustomAttribute ({metadataFile.Metadata.GetTableRowCount(TableIndex.CustomAttribute)})";
 
 		public override object Icon => Images.Literal;
 
@@ -44,14 +42,14 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			tabPage.SupportsLanguageSwitching = false;
 
 			var view = Helpers.PrepareDataGrid(tabPage, this);
-			var metadata = module.Metadata;
+			var metadata = metadataFile.Metadata;
 
 			var list = new List<CustomAttributeEntry>();
 			CustomAttributeEntry scrollTargetEntry = default;
 
 			foreach (var row in metadata.CustomAttributes)
 			{
-				CustomAttributeEntry entry = new CustomAttributeEntry(module, row);
+				CustomAttributeEntry entry = new CustomAttributeEntry(metadataFile, row);
 				if (scrollTarget == MetadataTokens.GetRowNumber(row))
 				{
 					scrollTargetEntry = entry;
@@ -73,9 +71,7 @@ public override bool View(ViewModels.TabPageModel tabPage)
 
 		struct CustomAttributeEntry
 		{
-			readonly int metadataOffset;
-			readonly PEFile module;
-			readonly MetadataReader metadata;
+			readonly MetadataFile metadataFile;
 			readonly CustomAttributeHandle handle;
 			readonly CustomAttribute customAttr;
 
@@ -83,31 +79,31 @@ struct CustomAttributeEntry
 
 			public int Token => MetadataTokens.GetToken(handle);
 
-			public int Offset => metadataOffset
-				+ metadata.GetTableMetadataOffset(TableIndex.CustomAttribute)
-				+ metadata.GetTableRowSize(TableIndex.CustomAttribute) * (RID - 1);
+			public int Offset => metadataFile.MetadataOffset
+				+ metadataFile.Metadata.GetTableMetadataOffset(TableIndex.CustomAttribute)
+				+ metadataFile.Metadata.GetTableRowSize(TableIndex.CustomAttribute) * (RID - 1);
 
 			[ColumnInfo("X8", Kind = ColumnKind.Token)]
 			public int Parent => MetadataTokens.GetToken(customAttr.Parent);
 
 			public void OnParentClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, customAttr.Parent, protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, customAttr.Parent, protocol: "metadata"));
 			}
 
 			string parentTooltip;
-			public string ParentTooltip => GenerateTooltip(ref parentTooltip, module, customAttr.Parent);
+			public string ParentTooltip => GenerateTooltip(ref parentTooltip, metadataFile, customAttr.Parent);
 
 			[ColumnInfo("X8", Kind = ColumnKind.Token)]
 			public int Constructor => MetadataTokens.GetToken(customAttr.Constructor);
 
 			public void OnConstructorClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, customAttr.Constructor, protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, customAttr.Constructor, protocol: "metadata"));
 			}
 
 			string constructorTooltip;
-			public string ConstructorTooltip => GenerateTooltip(ref constructorTooltip, module, customAttr.Constructor);
+			public string ConstructorTooltip => GenerateTooltip(ref constructorTooltip, metadataFile, customAttr.Constructor);
 
 			[ColumnInfo("X8", Kind = ColumnKind.HeapOffset)]
 			public int Value => MetadataTokens.GetHeapOffset(customAttr.Value);
@@ -118,13 +114,11 @@ public string ValueTooltip {
 				}
 			}
 
-			public CustomAttributeEntry(PEFile module, CustomAttributeHandle handle)
+			public CustomAttributeEntry(MetadataFile metadataFile, CustomAttributeHandle handle)
 			{
-				this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
-				this.module = module;
-				this.metadata = module.Metadata;
+				this.metadataFile = metadataFile;
 				this.handle = handle;
-				this.customAttr = metadata.GetCustomAttribute(handle);
+				this.customAttr = metadataFile.Metadata.GetCustomAttribute(handle);
 				this.parentTooltip = null;
 				this.constructorTooltip = null;
 			}
diff --git a/ILSpy/Metadata/CorTables/DeclSecurityTableTreeNode.cs b/ILSpy/Metadata/CorTables/DeclSecurityTableTreeNode.cs
index 601b7a8b13..cb423bbb0f 100644
--- a/ILSpy/Metadata/CorTables/DeclSecurityTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/DeclSecurityTableTreeNode.cs
@@ -22,20 +22,18 @@
 using System.Reflection.Metadata.Ecma335;
 
 using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.Disassembler;
-using ICSharpCode.Decompiler.IL;
 using ICSharpCode.Decompiler.Metadata;
 
 namespace ICSharpCode.ILSpy.Metadata
 {
 	class DeclSecurityTableTreeNode : MetadataTableTreeNode
 	{
-		public DeclSecurityTableTreeNode(PEFile module)
-			: base(HandleKind.DeclarativeSecurityAttribute, module)
+		public DeclSecurityTableTreeNode(MetadataFile metadataFile)
+			: base(HandleKind.DeclarativeSecurityAttribute, metadataFile)
 		{
 		}
 
-		public override object Text => $"0E DeclSecurity ({module.Metadata.GetTableRowCount(TableIndex.DeclSecurity)})";
+		public override object Text => $"0E DeclSecurity ({metadataFile.Metadata.GetTableRowCount(TableIndex.DeclSecurity)})";
 
 		public override object Icon => Images.Literal;
 
@@ -45,14 +43,14 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			tabPage.SupportsLanguageSwitching = false;
 
 			var view = Helpers.PrepareDataGrid(tabPage, this);
-			var metadata = module.Metadata;
+			var metadata = metadataFile.Metadata;
 
 			var list = new List<DeclSecurityEntry>();
 			DeclSecurityEntry scrollTargetEntry = default;
 
 			foreach (var row in metadata.DeclarativeSecurityAttributes)
 			{
-				var entry = new DeclSecurityEntry(module, row);
+				var entry = new DeclSecurityEntry(metadataFile, row);
 				if (scrollTarget == MetadataTokens.GetRowNumber(row))
 				{
 					scrollTargetEntry = entry;
@@ -74,9 +72,7 @@ public override bool View(ViewModels.TabPageModel tabPage)
 
 		struct DeclSecurityEntry
 		{
-			readonly int metadataOffset;
-			readonly PEFile module;
-			readonly MetadataReader metadata;
+			readonly MetadataFile metadataFile;
 			readonly DeclarativeSecurityAttributeHandle handle;
 			readonly DeclarativeSecurityAttribute declSecAttr;
 
@@ -84,20 +80,20 @@ struct DeclSecurityEntry
 
 			public int Token => MetadataTokens.GetToken(handle);
 
-			public int Offset => metadataOffset
-				+ metadata.GetTableMetadataOffset(TableIndex.DeclSecurity)
-				+ metadata.GetTableRowSize(TableIndex.DeclSecurity) * (RID - 1);
+			public int Offset => metadataFile.MetadataOffset
+				+ metadataFile.Metadata.GetTableMetadataOffset(TableIndex.DeclSecurity)
+				+ metadataFile.Metadata.GetTableRowSize(TableIndex.DeclSecurity) * (RID - 1);
 
 			[ColumnInfo("X8", Kind = ColumnKind.Token)]
 			public int Parent => MetadataTokens.GetToken(declSecAttr.Parent);
 
 			public void OnParentClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, declSecAttr.Parent, protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, declSecAttr.Parent, protocol: "metadata"));
 			}
 
 			string parentTooltip;
-			public string ParentTooltip => GenerateTooltip(ref parentTooltip, module, declSecAttr.Parent);
+			public string ParentTooltip => GenerateTooltip(ref parentTooltip, metadataFile, declSecAttr.Parent);
 
 			[ColumnInfo("X8", Kind = ColumnKind.Other)]
 			public DeclarativeSecurityAction Action => declSecAttr.Action;
@@ -117,13 +113,11 @@ public string PermissionSetTooltip {
 				}
 			}
 
-			public DeclSecurityEntry(PEFile module, DeclarativeSecurityAttributeHandle handle)
+			public DeclSecurityEntry(MetadataFile metadataFile, DeclarativeSecurityAttributeHandle handle)
 			{
-				this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
-				this.module = module;
-				this.metadata = module.Metadata;
+				this.metadataFile = metadataFile;
 				this.handle = handle;
-				this.declSecAttr = metadata.GetDeclarativeSecurityAttribute(handle);
+				this.declSecAttr = metadataFile.Metadata.GetDeclarativeSecurityAttribute(handle);
 				this.parentTooltip = null;
 			}
 		}
diff --git a/ILSpy/Metadata/CorTables/EventMapTableTreeNode.cs b/ILSpy/Metadata/CorTables/EventMapTableTreeNode.cs
index 1d94b78c21..001440f145 100644
--- a/ILSpy/Metadata/CorTables/EventMapTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/EventMapTableTreeNode.cs
@@ -22,20 +22,18 @@
 using System.Reflection.Metadata.Ecma335;
 
 using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.Disassembler;
-using ICSharpCode.Decompiler.IL;
 using ICSharpCode.Decompiler.Metadata;
 
 namespace ICSharpCode.ILSpy.Metadata
 {
 	class EventMapTableTreeNode : MetadataTableTreeNode
 	{
-		public EventMapTableTreeNode(PEFile module)
-			: base((HandleKind)0x12, module)
+		public EventMapTableTreeNode(MetadataFile metadataFile)
+			: base((HandleKind)0x12, metadataFile)
 		{
 		}
 
-		public override object Text => $"12 EventMap ({module.Metadata.GetTableRowCount(TableIndex.EventMap)})";
+		public override object Text => $"12 EventMap ({metadataFile.Metadata.GetTableRowCount(TableIndex.EventMap)})";
 
 		public override object Icon => Images.Literal;
 
@@ -45,17 +43,16 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			tabPage.SupportsLanguageSwitching = false;
 
 			var view = Helpers.PrepareDataGrid(tabPage, this);
-			var metadata = module.Metadata;
+			var metadata = metadataFile.Metadata;
 
 			var list = new List<EventMapEntry>();
 			EventMapEntry scrollTargetEntry = default;
 
 			var length = metadata.GetTableRowCount(TableIndex.EventMap);
 			ReadOnlySpan<byte> ptr = metadata.AsReadOnlySpan();
-			int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
 			for (int rid = 1; rid <= length; rid++)
 			{
-				EventMapEntry entry = new EventMapEntry(module, ptr, metadataOffset, rid);
+				EventMapEntry entry = new EventMapEntry(metadataFile, ptr, rid);
 				if (entry.RID == this.scrollTarget)
 				{
 					scrollTargetEntry = entry;
@@ -89,8 +86,7 @@ public EventMap(ReadOnlySpan<byte> ptr, int typeDefSize, int eventDefSize)
 
 		struct EventMapEntry
 		{
-			readonly PEFile module;
-			readonly MetadataReader metadata;
+			readonly MetadataFile metadataFile;
 			readonly EventMap eventMap;
 
 			public int RID { get; }
@@ -104,33 +100,32 @@ struct EventMapEntry
 
 			public void OnParentClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, eventMap.Parent, protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, eventMap.Parent, protocol: "metadata"));
 			}
 
 			string parentTooltip;
-			public string ParentTooltip => GenerateTooltip(ref parentTooltip, module, eventMap.Parent);
+			public string ParentTooltip => GenerateTooltip(ref parentTooltip, metadataFile, eventMap.Parent);
 
 			[ColumnInfo("X8", Kind = ColumnKind.Token)]
 			public int EventList => MetadataTokens.GetToken(eventMap.EventList);
 
 			public void OnEventListClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, eventMap.EventList, protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, eventMap.EventList, protocol: "metadata"));
 			}
 
 			string eventListTooltip;
-			public string EventListTooltip => GenerateTooltip(ref eventListTooltip, module, eventMap.EventList);
+			public string EventListTooltip => GenerateTooltip(ref eventListTooltip, metadataFile, eventMap.EventList);
 
-			public EventMapEntry(PEFile module, ReadOnlySpan<byte> ptr, int metadataOffset, int row)
+			public EventMapEntry(MetadataFile metadataFile, ReadOnlySpan<byte> ptr, int row)
 			{
-				this.module = module;
-				this.metadata = module.Metadata;
+				this.metadataFile = metadataFile;
 				this.RID = row;
-				var rowOffset = metadata.GetTableMetadataOffset(TableIndex.EventMap)
-					+ metadata.GetTableRowSize(TableIndex.EventMap) * (row - 1);
-				this.Offset = metadataOffset + rowOffset;
-				int typeDefSize = metadata.GetTableRowCount(TableIndex.TypeDef) < ushort.MaxValue ? 2 : 4;
-				int eventDefSize = metadata.GetTableRowCount(TableIndex.Event) < ushort.MaxValue ? 2 : 4;
+				var rowOffset = metadataFile.Metadata.GetTableMetadataOffset(TableIndex.EventMap)
+					+ metadataFile.Metadata.GetTableRowSize(TableIndex.EventMap) * (row - 1);
+				this.Offset = metadataFile.MetadataOffset + rowOffset;
+				int typeDefSize = metadataFile.Metadata.GetTableRowCount(TableIndex.TypeDef) < ushort.MaxValue ? 2 : 4;
+				int eventDefSize = metadataFile.Metadata.GetTableRowCount(TableIndex.Event) < ushort.MaxValue ? 2 : 4;
 				this.eventMap = new EventMap(ptr.Slice(rowOffset), typeDefSize, eventDefSize);
 				this.parentTooltip = null;
 				this.eventListTooltip = null;
diff --git a/ILSpy/Metadata/CorTables/EventTableTreeNode.cs b/ILSpy/Metadata/CorTables/EventTableTreeNode.cs
index b24f093dc6..c53fdf8a10 100644
--- a/ILSpy/Metadata/CorTables/EventTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/EventTableTreeNode.cs
@@ -22,8 +22,6 @@
 using System.Reflection.Metadata.Ecma335;
 
 using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.Disassembler;
-using ICSharpCode.Decompiler.IL;
 using ICSharpCode.Decompiler.Metadata;
 using ICSharpCode.Decompiler.TypeSystem;
 using ICSharpCode.ILSpy.TreeNodes;
@@ -32,12 +30,12 @@ namespace ICSharpCode.ILSpy.Metadata
 {
 	internal class EventTableTreeNode : MetadataTableTreeNode
 	{
-		public EventTableTreeNode(PEFile module)
-			: base(HandleKind.EventDefinition, module)
+		public EventTableTreeNode(MetadataFile metadataFile)
+			: base(HandleKind.EventDefinition, metadataFile)
 		{
 		}
 
-		public override object Text => $"14 Event ({module.Metadata.GetTableRowCount(TableIndex.Event)})";
+		public override object Text => $"14 Event ({metadataFile.Metadata.GetTableRowCount(TableIndex.Event)})";
 
 		public override object Icon => Images.Literal;
 
@@ -47,14 +45,14 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			tabPage.SupportsLanguageSwitching = false;
 
 			var view = Helpers.PrepareDataGrid(tabPage, this);
-			var metadata = module.Metadata;
+			var metadata = metadataFile.Metadata;
 
 			var list = new List<EventDefEntry>();
 			EventDefEntry scrollTargetEntry = default;
 
 			foreach (var row in metadata.EventDefinitions)
 			{
-				EventDefEntry entry = new EventDefEntry(module, row);
+				EventDefEntry entry = new EventDefEntry(metadataFile, row);
 				if (entry.RID == this.scrollTarget)
 				{
 					scrollTargetEntry = entry;
@@ -76,9 +74,7 @@ public override bool View(ViewModels.TabPageModel tabPage)
 
 		struct EventDefEntry : IMemberTreeNode
 		{
-			readonly int metadataOffset;
-			readonly PEFile module;
-			readonly MetadataReader metadata;
+			readonly MetadataFile metadataFile;
 			readonly EventDefinitionHandle handle;
 			readonly EventDefinition eventDef;
 
@@ -86,9 +82,9 @@ struct EventDefEntry : IMemberTreeNode
 
 			public int Token => MetadataTokens.GetToken(handle);
 
-			public int Offset => metadataOffset
-				+ metadata.GetTableMetadataOffset(TableIndex.Event)
-				+ metadata.GetTableRowSize(TableIndex.Event) * (RID - 1);
+			public int Offset => metadataFile.MetadataOffset
+				+ metadataFile.Metadata.GetTableMetadataOffset(TableIndex.Event)
+				+ metadataFile.Metadata.GetTableRowSize(TableIndex.Event) * (RID - 1);
 
 			[ColumnInfo("X8", Kind = ColumnKind.Other)]
 			public EventAttributes Attributes => eventDef.Attributes;
@@ -99,28 +95,30 @@ struct EventDefEntry : IMemberTreeNode
 
 			public string NameTooltip => $"{MetadataTokens.GetHeapOffset(eventDef.Name):X} \"{Name}\"";
 
-			public string Name => metadata.GetString(eventDef.Name);
+			public string Name => metadataFile.Metadata.GetString(eventDef.Name);
 
-			IEntity IMemberTreeNode.Member => ((MetadataModule)module.GetTypeSystemWithCurrentOptionsOrNull()?.MainModule).GetDefinition(handle);
+			IEntity IMemberTreeNode.Member {
+				get {
+					return ((MetadataModule)metadataFile.GetTypeSystemWithCurrentOptionsOrNull()?.MainModule)?.GetDefinition(handle);
+				}
+			}
 
 			[ColumnInfo("X8", Kind = ColumnKind.Token)]
 			public int Type => MetadataTokens.GetToken(eventDef.Type);
 
 			public void OnTypeClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, eventDef.Type, protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, eventDef.Type, protocol: "metadata"));
 			}
 
 			string typeTooltip;
-			public string TypeTooltip => GenerateTooltip(ref typeTooltip, module, eventDef.Type);
+			public string TypeTooltip => GenerateTooltip(ref typeTooltip, metadataFile, eventDef.Type);
 
-			public EventDefEntry(PEFile module, EventDefinitionHandle handle)
+			public EventDefEntry(MetadataFile metadataFile, EventDefinitionHandle handle)
 			{
-				this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
-				this.module = module;
-				this.metadata = module.Metadata;
+				this.metadataFile = metadataFile;
 				this.handle = handle;
-				this.eventDef = metadata.GetEventDefinition(handle);
+				this.eventDef = metadataFile.Metadata.GetEventDefinition(handle);
 				this.typeTooltip = null;
 			}
 		}
diff --git a/ILSpy/Metadata/CorTables/ExportedTypeTableTreeNode.cs b/ILSpy/Metadata/CorTables/ExportedTypeTableTreeNode.cs
index b95a5a9e8e..70b5470331 100644
--- a/ILSpy/Metadata/CorTables/ExportedTypeTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/ExportedTypeTableTreeNode.cs
@@ -22,19 +22,18 @@
 using System.Reflection.Metadata.Ecma335;
 
 using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.IL;
 using ICSharpCode.Decompiler.Metadata;
 
 namespace ICSharpCode.ILSpy.Metadata
 {
 	internal class ExportedTypeTableTreeNode : MetadataTableTreeNode
 	{
-		public ExportedTypeTableTreeNode(PEFile module)
-			: base(HandleKind.ExportedType, module)
+		public ExportedTypeTableTreeNode(MetadataFile metadataFile)
+			: base(HandleKind.ExportedType, metadataFile)
 		{
 		}
 
-		public override object Text => $"27 ExportedType ({module.Metadata.GetTableRowCount(TableIndex.ExportedType)})";
+		public override object Text => $"27 ExportedType ({metadataFile.Metadata.GetTableRowCount(TableIndex.ExportedType)})";
 
 		public override object Icon => Images.Literal;
 
@@ -44,13 +43,13 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			tabPage.SupportsLanguageSwitching = false;
 
 			var view = Helpers.PrepareDataGrid(tabPage, this);
-			var metadata = module.Metadata;
+			var metadata = metadataFile.Metadata;
 			var list = new List<ExportedTypeEntry>();
 			ExportedTypeEntry scrollTargetEntry = default;
 
 			foreach (var row in metadata.ExportedTypes)
 			{
-				ExportedTypeEntry entry = new ExportedTypeEntry(module.Reader.PEHeaders.MetadataStartOffset, module, row, metadata.GetExportedType(row));
+				ExportedTypeEntry entry = new ExportedTypeEntry(metadataFile, row, metadataFile.Metadata.GetExportedType(row));
 				if (entry.RID == this.scrollTarget)
 				{
 					scrollTargetEntry = entry;
@@ -72,9 +71,7 @@ public override bool View(ViewModels.TabPageModel tabPage)
 
 		struct ExportedTypeEntry
 		{
-			readonly int metadataOffset;
-			readonly PEFile module;
-			readonly MetadataReader metadata;
+			readonly MetadataFile metadataFile;
 			readonly ExportedTypeHandle handle;
 			readonly ExportedType type;
 
@@ -82,9 +79,9 @@ struct ExportedTypeEntry
 
 			public int Token => MetadataTokens.GetToken(handle);
 
-			public int Offset => metadataOffset
-				+ metadata.GetTableMetadataOffset(TableIndex.ExportedType)
-				+ metadata.GetTableRowSize(TableIndex.ExportedType) * (RID - 1);
+			public int Offset => metadataFile.MetadataOffset
+				+ metadataFile.Metadata.GetTableMetadataOffset(TableIndex.ExportedType)
+				+ metadataFile.Metadata.GetTableRowSize(TableIndex.ExportedType) * (RID - 1);
 
 			[ColumnInfo("X8", Kind = ColumnKind.Other)]
 			public TypeAttributes Attributes => type.Attributes;
@@ -104,28 +101,26 @@ struct ExportedTypeEntry
 
 			public string TypeNameTooltip => $"{MetadataTokens.GetHeapOffset(type.Name):X} \"{TypeName}\"";
 
-			public string TypeName => metadata.GetString(type.Name);
+			public string TypeName => metadataFile.Metadata.GetString(type.Name);
 
 			public string TypeNamespaceTooltip => $"{MetadataTokens.GetHeapOffset(type.Namespace):X} \"{TypeNamespace}\"";
 
-			public string TypeNamespace => metadata.GetString(type.Namespace);
+			public string TypeNamespace => metadataFile.Metadata.GetString(type.Namespace);
 
 			[ColumnInfo("X8", Kind = ColumnKind.Token)]
 			public int Implementation => MetadataTokens.GetToken(type.Implementation);
 
 			public void OnImplementationClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, type.Implementation, protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, type.Implementation, protocol: "metadata"));
 			}
 
 			string implementationTooltip;
-			public string ImplementationTooltip => GenerateTooltip(ref implementationTooltip, module, type.Implementation);
+			public string ImplementationTooltip => GenerateTooltip(ref implementationTooltip, metadataFile, type.Implementation);
 
-			public ExportedTypeEntry(int metadataOffset, PEFile module, ExportedTypeHandle handle, ExportedType type)
+			public ExportedTypeEntry(MetadataFile metadataFile, ExportedTypeHandle handle, ExportedType type)
 			{
-				this.metadataOffset = metadataOffset;
-				this.module = module;
-				this.metadata = module.Metadata;
+				this.metadataFile = metadataFile;
 				this.handle = handle;
 				this.type = type;
 				this.implementationTooltip = null;
diff --git a/ILSpy/Metadata/CorTables/FieldLayoutTableTreeNode.cs b/ILSpy/Metadata/CorTables/FieldLayoutTableTreeNode.cs
index f5da959eb7..85a5acdc6d 100644
--- a/ILSpy/Metadata/CorTables/FieldLayoutTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/FieldLayoutTableTreeNode.cs
@@ -23,20 +23,18 @@
 using System.Reflection.Metadata.Ecma335;
 
 using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.Disassembler;
-using ICSharpCode.Decompiler.IL;
 using ICSharpCode.Decompiler.Metadata;
 
 namespace ICSharpCode.ILSpy.Metadata
 {
 	internal class FieldLayoutTableTreeNode : MetadataTableTreeNode
 	{
-		public FieldLayoutTableTreeNode(PEFile module)
-			: base((HandleKind)0x10, module)
+		public FieldLayoutTableTreeNode(MetadataFile metadataFile)
+			: base((HandleKind)0x10, metadataFile)
 		{
 		}
 
-		public override object Text => $"10 FieldLayout ({module.Metadata.GetTableRowCount(TableIndex.FieldLayout)})";
+		public override object Text => $"10 FieldLayout ({metadataFile.Metadata.GetTableRowCount(TableIndex.FieldLayout)})";
 
 		public override object Icon => Images.Literal;
 
@@ -46,17 +44,16 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			tabPage.SupportsLanguageSwitching = false;
 
 			var view = Helpers.PrepareDataGrid(tabPage, this);
-			var metadata = module.Metadata;
+			var metadata = metadataFile.Metadata;
 
 			var list = new List<FieldLayoutEntry>();
 			FieldLayoutEntry scrollTargetEntry = default;
 
 			var length = metadata.GetTableRowCount(TableIndex.FieldLayout);
 			ReadOnlySpan<byte> ptr = metadata.AsReadOnlySpan();
-			int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
 			for (int rid = 1; rid <= length; rid++)
 			{
-				FieldLayoutEntry entry = new FieldLayoutEntry(module, ptr, metadataOffset, rid);
+				FieldLayoutEntry entry = new FieldLayoutEntry(metadataFile, ptr, rid);
 				if (entry.RID == this.scrollTarget)
 				{
 					scrollTargetEntry = entry;
@@ -90,8 +87,7 @@ public FieldLayout(ReadOnlySpan<byte> ptr, int fieldDefSize)
 
 		struct FieldLayoutEntry
 		{
-			readonly PEFile module;
-			readonly MetadataReader metadata;
+			readonly MetadataFile metadataFile;
 			readonly FieldLayout fieldLayout;
 
 			public int RID { get; }
@@ -105,24 +101,23 @@ struct FieldLayoutEntry
 
 			public void OnFieldClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, fieldLayout.Field, protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, fieldLayout.Field, protocol: "metadata"));
 			}
 
 			string fieldTooltip;
-			public string FieldTooltip => GenerateTooltip(ref fieldTooltip, module, fieldLayout.Field);
+			public string FieldTooltip => GenerateTooltip(ref fieldTooltip, metadataFile, fieldLayout.Field);
 
 			[ColumnInfo("X8", Kind = ColumnKind.Other)]
 			public int FieldOffset => fieldLayout.Offset;
 
-			public FieldLayoutEntry(PEFile module, ReadOnlySpan<byte> ptr, int metadataOffset, int row)
+			public FieldLayoutEntry(MetadataFile metadataFile, ReadOnlySpan<byte> ptr, int row)
 			{
-				this.module = module;
-				this.metadata = module.Metadata;
+				this.metadataFile = metadataFile;
 				this.RID = row;
-				var rowOffset = metadata.GetTableMetadataOffset(TableIndex.FieldLayout)
-					+ metadata.GetTableRowSize(TableIndex.FieldLayout) * (row - 1);
-				this.Offset = metadataOffset + rowOffset;
-				int fieldDefSize = metadata.GetTableRowCount(TableIndex.Field) < ushort.MaxValue ? 2 : 4;
+				var rowOffset = metadataFile.Metadata.GetTableMetadataOffset(TableIndex.FieldLayout)
+					+ metadataFile.Metadata.GetTableRowSize(TableIndex.FieldLayout) * (row - 1);
+				this.Offset = metadataFile.MetadataOffset + rowOffset;
+				int fieldDefSize = metadataFile.Metadata.GetTableRowCount(TableIndex.Field) < ushort.MaxValue ? 2 : 4;
 				this.fieldLayout = new FieldLayout(ptr.Slice(rowOffset), fieldDefSize);
 				this.fieldTooltip = null;
 			}
diff --git a/ILSpy/Metadata/CorTables/FieldMarshalTableTreeNode.cs b/ILSpy/Metadata/CorTables/FieldMarshalTableTreeNode.cs
index b6cc9771eb..6624d9bb52 100644
--- a/ILSpy/Metadata/CorTables/FieldMarshalTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/FieldMarshalTableTreeNode.cs
@@ -22,20 +22,18 @@
 using System.Reflection.Metadata.Ecma335;
 
 using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.Disassembler;
-using ICSharpCode.Decompiler.IL;
 using ICSharpCode.Decompiler.Metadata;
 
 namespace ICSharpCode.ILSpy.Metadata
 {
 	internal class FieldMarshalTableTreeNode : MetadataTableTreeNode
 	{
-		public FieldMarshalTableTreeNode(PEFile module)
-			: base((HandleKind)0x0D, module)
+		public FieldMarshalTableTreeNode(MetadataFile metadataFile)
+			: base((HandleKind)0x0D, metadataFile)
 		{
 		}
 
-		public override object Text => $"0D FieldMarshal ({module.Metadata.GetTableRowCount(TableIndex.FieldMarshal)})";
+		public override object Text => $"0D FieldMarshal ({metadataFile.Metadata.GetTableRowCount(TableIndex.FieldMarshal)})";
 
 		public override object Icon => Images.Literal;
 
@@ -45,17 +43,16 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			tabPage.SupportsLanguageSwitching = false;
 
 			var view = Helpers.PrepareDataGrid(tabPage, this);
-			var metadata = module.Metadata;
+			var metadata = metadataFile.Metadata;
 
 			var list = new List<FieldMarshalEntry>();
 			FieldMarshalEntry scrollTargetEntry = default;
 
 			var length = metadata.GetTableRowCount(TableIndex.FieldMarshal);
 			ReadOnlySpan<byte> ptr = metadata.AsReadOnlySpan();
-			int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
 			for (int rid = 1; rid <= length; rid++)
 			{
-				FieldMarshalEntry entry = new FieldMarshalEntry(module, ptr, metadataOffset, rid);
+				FieldMarshalEntry entry = new FieldMarshalEntry(metadataFile, ptr, rid);
 				if (entry.RID == this.scrollTarget)
 				{
 					scrollTargetEntry = entry;
@@ -89,8 +86,7 @@ public FieldMarshal(ReadOnlySpan<byte> ptr, int blobHeapSize, int hasFieldMarsha
 
 		struct FieldMarshalEntry
 		{
-			readonly PEFile module;
-			readonly MetadataReader metadata;
+			readonly MetadataFile metadataFile;
 			readonly FieldMarshal fieldMarshal;
 
 			public int RID { get; }
@@ -104,25 +100,24 @@ struct FieldMarshalEntry
 
 			public void OnParentClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, fieldMarshal.Parent, protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, fieldMarshal.Parent, protocol: "metadata"));
 			}
 
 			string parentTooltip;
-			public string ParentTooltip => GenerateTooltip(ref parentTooltip, module, fieldMarshal.Parent);
+			public string ParentTooltip => GenerateTooltip(ref parentTooltip, metadataFile, fieldMarshal.Parent);
 
 			[ColumnInfo("X8", Kind = ColumnKind.HeapOffset)]
 			public int NativeType => MetadataTokens.GetHeapOffset(fieldMarshal.NativeType);
 
-			public FieldMarshalEntry(PEFile module, ReadOnlySpan<byte> ptr, int metadataOffset, int row)
+			public FieldMarshalEntry(MetadataFile metadataFile, ReadOnlySpan<byte> ptr, int row)
 			{
-				this.module = module;
-				this.metadata = module.Metadata;
+				this.metadataFile = metadataFile;
 				this.RID = row;
-				var rowOffset = metadata.GetTableMetadataOffset(TableIndex.FieldMarshal)
-					+ metadata.GetTableRowSize(TableIndex.FieldMarshal) * (row - 1);
-				this.Offset = metadataOffset + rowOffset;
-				int hasFieldMarshalRefSize = metadata.ComputeCodedTokenSize(32768, TableMask.Field | TableMask.Param);
-				int blobHeapSize = metadata.GetHeapSize(HeapIndex.Blob) < ushort.MaxValue ? 2 : 4;
+				var rowOffset = metadataFile.Metadata.GetTableMetadataOffset(TableIndex.FieldMarshal)
+					+ metadataFile.Metadata.GetTableRowSize(TableIndex.FieldMarshal) * (row - 1);
+				this.Offset = metadataFile.MetadataOffset + rowOffset;
+				int hasFieldMarshalRefSize = metadataFile.Metadata.ComputeCodedTokenSize(32768, TableMask.Field | TableMask.Param);
+				int blobHeapSize = metadataFile.Metadata.GetHeapSize(HeapIndex.Blob) < ushort.MaxValue ? 2 : 4;
 				this.fieldMarshal = new FieldMarshal(ptr.Slice(rowOffset), blobHeapSize, hasFieldMarshalRefSize);
 				this.parentTooltip = null;
 			}
diff --git a/ILSpy/Metadata/CorTables/FieldRVATableTreeNode.cs b/ILSpy/Metadata/CorTables/FieldRVATableTreeNode.cs
index dc34c5c23c..ac8c8fc2eb 100644
--- a/ILSpy/Metadata/CorTables/FieldRVATableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/FieldRVATableTreeNode.cs
@@ -23,20 +23,18 @@
 using System.Reflection.Metadata.Ecma335;
 
 using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.Disassembler;
-using ICSharpCode.Decompiler.IL;
 using ICSharpCode.Decompiler.Metadata;
 
 namespace ICSharpCode.ILSpy.Metadata
 {
 	internal class FieldRVATableTreeNode : MetadataTableTreeNode
 	{
-		public FieldRVATableTreeNode(PEFile module)
-			: base((HandleKind)0x1D, module)
+		public FieldRVATableTreeNode(MetadataFile metadataFile)
+			: base((HandleKind)0x1D, metadataFile)
 		{
 		}
 
-		public override object Text => $"1D FieldRVA ({module.Metadata.GetTableRowCount(TableIndex.FieldRva)})";
+		public override object Text => $"1D FieldRVA ({metadataFile.Metadata.GetTableRowCount(TableIndex.FieldRva)})";
 
 		public override object Icon => Images.Literal;
 
@@ -46,17 +44,17 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			tabPage.SupportsLanguageSwitching = false;
 
 			var view = Helpers.PrepareDataGrid(tabPage, this);
-			var metadata = module.Metadata;
+			var metadata = metadataFile.Metadata;
 
 			var list = new List<FieldRVAEntry>();
 			FieldRVAEntry scrollTargetEntry = default;
 
 			var length = metadata.GetTableRowCount(TableIndex.FieldRva);
 			ReadOnlySpan<byte> ptr = metadata.AsReadOnlySpan();
-			int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
+			int metadataOffset = metadataFile.MetadataOffset;
 			for (int rid = 1; rid <= length; rid++)
 			{
-				FieldRVAEntry entry = new FieldRVAEntry(module, ptr, metadataOffset, rid);
+				FieldRVAEntry entry = new FieldRVAEntry(metadataFile, metadataOffset, ptr, rid);
 				if (entry.RID == this.scrollTarget)
 				{
 					scrollTargetEntry = entry;
@@ -90,8 +88,7 @@ public FieldRVA(ReadOnlySpan<byte> ptr, int fieldDefSize)
 
 		struct FieldRVAEntry
 		{
-			readonly PEFile module;
-			readonly MetadataReader metadata;
+			readonly MetadataFile metadataFile;
 			readonly FieldRVA fieldRVA;
 
 			public int RID { get; }
@@ -105,24 +102,23 @@ struct FieldRVAEntry
 
 			public void OnFieldClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, fieldRVA.Field, protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, fieldRVA.Field, protocol: "metadata"));
 			}
 
 			string fieldTooltip;
-			public string FieldTooltip => GenerateTooltip(ref fieldTooltip, module, fieldRVA.Field);
+			public string FieldTooltip => GenerateTooltip(ref fieldTooltip, metadataFile, fieldRVA.Field);
 
 			[ColumnInfo("X8", Kind = ColumnKind.Other)]
 			public int FieldOffset => fieldRVA.Offset;
 
-			public FieldRVAEntry(PEFile module, ReadOnlySpan<byte> ptr, int metadataOffset, int row)
+			public FieldRVAEntry(MetadataFile metadataFile, int metadataOffset, ReadOnlySpan<byte> ptr, int row)
 			{
-				this.module = module;
-				this.metadata = module.Metadata;
+				this.metadataFile = metadataFile;
 				this.RID = row;
-				var rowOffset = metadata.GetTableMetadataOffset(TableIndex.FieldRva)
-					+ metadata.GetTableRowSize(TableIndex.FieldRva) * (row - 1);
+				var rowOffset = metadataFile.Metadata.GetTableMetadataOffset(TableIndex.FieldRva)
+					+ metadataFile.Metadata.GetTableRowSize(TableIndex.FieldRva) * (row - 1);
 				this.Offset = metadataOffset + rowOffset;
-				int fieldDefSize = metadata.GetTableRowCount(TableIndex.Field) < ushort.MaxValue ? 2 : 4;
+				int fieldDefSize = metadataFile.Metadata.GetTableRowCount(TableIndex.Field) < ushort.MaxValue ? 2 : 4;
 				this.fieldRVA = new FieldRVA(ptr.Slice(rowOffset), fieldDefSize);
 				this.fieldTooltip = null;
 			}
diff --git a/ILSpy/Metadata/CorTables/FieldTableTreeNode.cs b/ILSpy/Metadata/CorTables/FieldTableTreeNode.cs
index f036661682..2e48a1476e 100644
--- a/ILSpy/Metadata/CorTables/FieldTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/FieldTableTreeNode.cs
@@ -21,13 +21,8 @@
 using System.Reflection;
 using System.Reflection.Metadata;
 using System.Reflection.Metadata.Ecma335;
-using System.Windows.Controls;
-using System.Windows.Input;
-using System.Windows.Threading;
 
 using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.Disassembler;
-using ICSharpCode.Decompiler.IL;
 using ICSharpCode.Decompiler.Metadata;
 using ICSharpCode.Decompiler.TypeSystem;
 using ICSharpCode.ILSpy.TreeNodes;
@@ -36,12 +31,12 @@ namespace ICSharpCode.ILSpy.Metadata
 {
 	internal class FieldTableTreeNode : MetadataTableTreeNode
 	{
-		public FieldTableTreeNode(PEFile module)
-			: base(HandleKind.FieldDefinition, module)
+		public FieldTableTreeNode(MetadataFile metadataFile)
+			: base(HandleKind.FieldDefinition, metadataFile)
 		{
 		}
 
-		public override object Text => $"04 Field ({module.Metadata.GetTableRowCount(TableIndex.Field)})";
+		public override object Text => $"04 Field ({metadataFile.Metadata.GetTableRowCount(TableIndex.Field)})";
 
 		public override object Icon => Images.Literal;
 
@@ -50,7 +45,7 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			tabPage.Title = Text.ToString();
 			tabPage.SupportsLanguageSwitching = false;
 			var view = Helpers.PrepareDataGrid(tabPage, this);
-			var metadata = module.Metadata;
+			var metadata = metadataFile.Metadata;
 
 			var list = new List<FieldDefEntry>();
 
@@ -58,7 +53,7 @@ public override bool View(ViewModels.TabPageModel tabPage)
 
 			foreach (var row in metadata.FieldDefinitions)
 			{
-				var entry = new FieldDefEntry(module, row);
+				var entry = new FieldDefEntry(metadataFile, row);
 				if (scrollTarget == entry.RID)
 				{
 					scrollTargetEntry = entry;
@@ -80,9 +75,7 @@ public override bool View(ViewModels.TabPageModel tabPage)
 
 		struct FieldDefEntry : IMemberTreeNode
 		{
-			readonly int metadataOffset;
-			readonly PEFile module;
-			readonly MetadataReader metadata;
+			readonly MetadataFile metadataFile;
 			readonly FieldDefinitionHandle handle;
 			readonly FieldDefinition fieldDef;
 
@@ -90,9 +83,9 @@ struct FieldDefEntry : IMemberTreeNode
 
 			public int Token => MetadataTokens.GetToken(handle);
 
-			public int Offset => metadataOffset
-				+ metadata.GetTableMetadataOffset(TableIndex.Field)
-				+ metadata.GetTableRowSize(TableIndex.Field) * (RID - 1);
+			public int Offset => metadataFile.MetadataOffset
+				+ metadataFile.Metadata.GetTableMetadataOffset(TableIndex.Field)
+				+ metadataFile.Metadata.GetTableRowSize(TableIndex.Field) * (RID - 1);
 
 			[ColumnInfo("X8", Kind = ColumnKind.Other)]
 			public FieldAttributes Attributes => fieldDef.Attributes;
@@ -104,25 +97,23 @@ struct FieldDefEntry : IMemberTreeNode
 				FlagGroup.CreateMultipleChoiceGroup(typeof(FieldAttributes), "Flags:", (int)otherFlagsMask, (int)(fieldDef.Attributes & otherFlagsMask), includeAll: false),
 			};
 
-			public string Name => metadata.GetString(fieldDef.Name);
+			public string Name => metadataFile.Metadata.GetString(fieldDef.Name);
 
 			public string NameTooltip => $"{MetadataTokens.GetHeapOffset(fieldDef.Name):X} \"{Name}\"";
 
-			IEntity IMemberTreeNode.Member => ((MetadataModule)module.GetTypeSystemWithCurrentOptionsOrNull()?.MainModule).GetDefinition(handle);
+			IEntity IMemberTreeNode.Member => ((MetadataModule)metadataFile.GetTypeSystemWithCurrentOptionsOrNull()?.MainModule)?.GetDefinition(handle);
 
 			[ColumnInfo("X8", Kind = ColumnKind.HeapOffset)]
 			public int Signature => MetadataTokens.GetHeapOffset(fieldDef.Signature);
 
 			string signatureTooltip;
-			public string SignatureTooltip => GenerateTooltip(ref signatureTooltip, module, handle);
+			public string SignatureTooltip => GenerateTooltip(ref signatureTooltip, metadataFile, handle);
 
-			public FieldDefEntry(PEFile module, FieldDefinitionHandle handle)
+			public FieldDefEntry(MetadataFile metadataFile, FieldDefinitionHandle handle)
 			{
-				this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
-				this.module = module;
-				this.metadata = module.Metadata;
+				this.metadataFile = metadataFile;
 				this.handle = handle;
-				this.fieldDef = metadata.GetFieldDefinition(handle);
+				this.fieldDef = metadataFile.Metadata.GetFieldDefinition(handle);
 				this.signatureTooltip = null;
 			}
 		}
diff --git a/ILSpy/Metadata/CorTables/FileTableTreeNode.cs b/ILSpy/Metadata/CorTables/FileTableTreeNode.cs
index ddf0e51895..1d85d18c47 100644
--- a/ILSpy/Metadata/CorTables/FileTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/FileTableTreeNode.cs
@@ -27,12 +27,12 @@ namespace ICSharpCode.ILSpy.Metadata
 {
 	class FileTableTreeNode : MetadataTableTreeNode
 	{
-		public FileTableTreeNode(PEFile module)
-			: base(HandleKind.AssemblyFile, module)
+		public FileTableTreeNode(MetadataFile metadataFile)
+			: base(HandleKind.AssemblyFile, metadataFile)
 		{
 		}
 
-		public override object Text => $"26 File ({module.Metadata.GetTableRowCount(TableIndex.File)})";
+		public override object Text => $"26 File ({metadataFile.Metadata.GetTableRowCount(TableIndex.File)})";
 
 		public override object Icon => Images.Literal;
 
@@ -42,14 +42,14 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			tabPage.SupportsLanguageSwitching = false;
 
 			var view = Helpers.PrepareDataGrid(tabPage, this);
-			var metadata = module.Metadata;
+			var metadata = metadataFile.Metadata;
 
 			var list = new List<FileEntry>();
 			FileEntry scrollTargetEntry = default;
 
 			foreach (var row in metadata.AssemblyFiles)
 			{
-				FileEntry entry = new FileEntry(module, row);
+				FileEntry entry = new FileEntry(metadataFile, row);
 				if (entry.RID == this.scrollTarget)
 				{
 					scrollTargetEntry = entry;
@@ -71,9 +71,7 @@ public override bool View(ViewModels.TabPageModel tabPage)
 
 		struct FileEntry
 		{
-			readonly int metadataOffset;
-			readonly PEFile module;
-			readonly MetadataReader metadata;
+			readonly MetadataFile metadataFile;
 			readonly AssemblyFileHandle handle;
 			readonly AssemblyFile assemblyFile;
 
@@ -81,16 +79,16 @@ struct FileEntry
 
 			public int Token => MetadataTokens.GetToken(handle);
 
-			public int Offset => metadataOffset
-				+ metadata.GetTableMetadataOffset(TableIndex.File)
-				+ metadata.GetTableRowSize(TableIndex.File) * (RID - 1);
+			public int Offset => metadataFile.MetadataOffset
+				+ metadataFile.Metadata.GetTableMetadataOffset(TableIndex.File)
+				+ metadataFile.Metadata.GetTableRowSize(TableIndex.File) * (RID - 1);
 
 			[ColumnInfo("X8", Kind = ColumnKind.Other)]
 			public int Attributes => assemblyFile.ContainsMetadata ? 1 : 0;
 
 			public string AttributesTooltip => assemblyFile.ContainsMetadata ? "ContainsMetaData" : "ContainsNoMetaData";
 
-			public string Name => metadata.GetString(assemblyFile.Name);
+			public string Name => metadataFile.Metadata.GetString(assemblyFile.Name);
 
 			public string NameTooltip => $"{MetadataTokens.GetHeapOffset(assemblyFile.Name):X} \"{Name}\"";
 
@@ -101,18 +99,16 @@ public string HashValueTooltip {
 				get {
 					if (assemblyFile.HashValue.IsNil)
 						return null;
-					System.Collections.Immutable.ImmutableArray<byte> token = metadata.GetBlobContent(assemblyFile.HashValue);
+					System.Collections.Immutable.ImmutableArray<byte> token = metadataFile.Metadata.GetBlobContent(assemblyFile.HashValue);
 					return token.ToHexString(token.Length);
 				}
 			}
 
-			public FileEntry(PEFile module, AssemblyFileHandle handle)
+			public FileEntry(MetadataFile metadataFile, AssemblyFileHandle handle)
 			{
-				this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
-				this.module = module;
-				this.metadata = module.Metadata;
+				this.metadataFile = metadataFile;
 				this.handle = handle;
-				this.assemblyFile = metadata.GetAssemblyFile(handle);
+				this.assemblyFile = metadataFile.Metadata.GetAssemblyFile(handle);
 			}
 		}
 
diff --git a/ILSpy/Metadata/CorTables/GenericParamConstraintTableTreeNode.cs b/ILSpy/Metadata/CorTables/GenericParamConstraintTableTreeNode.cs
index 1f97fdce6f..cdc08a59a9 100644
--- a/ILSpy/Metadata/CorTables/GenericParamConstraintTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/GenericParamConstraintTableTreeNode.cs
@@ -21,7 +21,6 @@
 using System.Reflection.Metadata.Ecma335;
 
 using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.Disassembler;
 using ICSharpCode.Decompiler.IL;
 using ICSharpCode.Decompiler.Metadata;
 
@@ -29,12 +28,12 @@ namespace ICSharpCode.ILSpy.Metadata
 {
 	internal class GenericParamConstraintTableTreeNode : MetadataTableTreeNode
 	{
-		public GenericParamConstraintTableTreeNode(PEFile module)
-			: base(HandleKind.GenericParameterConstraint, module)
+		public GenericParamConstraintTableTreeNode(MetadataFile metadataFile)
+			: base(HandleKind.GenericParameterConstraint, metadataFile)
 		{
 		}
 
-		public override object Text => $"2C GenericParamConstraint ({module.Metadata.GetTableRowCount(TableIndex.GenericParamConstraint)})";
+		public override object Text => $"2C GenericParamConstraint ({metadataFile.Metadata.GetTableRowCount(TableIndex.GenericParamConstraint)})";
 
 		public override object Icon => Images.Literal;
 
@@ -44,14 +43,14 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			tabPage.SupportsLanguageSwitching = false;
 
 			var view = Helpers.PrepareDataGrid(tabPage, this);
-			var metadata = module.Metadata;
+			var metadata = metadataFile.Metadata;
 
 			var list = new List<GenericParamConstraintEntry>();
 			GenericParamConstraintEntry scrollTargetEntry = default;
 
 			for (int row = 1; row <= metadata.GetTableRowCount(TableIndex.GenericParamConstraint); row++)
 			{
-				GenericParamConstraintEntry entry = new GenericParamConstraintEntry(module, MetadataTokens.GenericParameterConstraintHandle(row));
+				GenericParamConstraintEntry entry = new GenericParamConstraintEntry(metadataFile, MetadataTokens.GenericParameterConstraintHandle(row));
 				if (entry.RID == this.scrollTarget)
 				{
 					scrollTargetEntry = entry;
@@ -72,9 +71,7 @@ public override bool View(ViewModels.TabPageModel tabPage)
 
 		struct GenericParamConstraintEntry
 		{
-			readonly int metadataOffset;
-			readonly PEFile module;
-			readonly MetadataReader metadata;
+			readonly MetadataFile metadataFile;
 			readonly GenericParameterConstraintHandle handle;
 			readonly GenericParameterConstraint genericParamConstraint;
 
@@ -82,16 +79,16 @@ struct GenericParamConstraintEntry
 
 			public int Token => MetadataTokens.GetToken(handle);
 
-			public int Offset => metadataOffset
-				+ metadata.GetTableMetadataOffset(TableIndex.GenericParamConstraint)
-				+ metadata.GetTableRowSize(TableIndex.GenericParamConstraint) * (RID - 1);
+			public int Offset => metadataFile.MetadataOffset
+				+ metadataFile.Metadata.GetTableMetadataOffset(TableIndex.GenericParamConstraint)
+				+ metadataFile.Metadata.GetTableRowSize(TableIndex.GenericParamConstraint) * (RID - 1);
 
 			[ColumnInfo("X8", Kind = ColumnKind.Token)]
 			public int Owner => MetadataTokens.GetToken(genericParamConstraint.Parameter);
 
 			public void OnOwnerClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, genericParamConstraint.Parameter, protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, genericParamConstraint.Parameter, protocol: "metadata"));
 			}
 
 			string ownerTooltip;
@@ -101,9 +98,9 @@ public string OwnerTooltip {
 					if (ownerTooltip == null)
 					{
 						ITextOutput output = new PlainTextOutput();
-						var p = metadata.GetGenericParameter(genericParamConstraint.Parameter);
-						output.Write("parameter " + p.Index + (p.Name.IsNil ? "" : " (" + metadata.GetString(p.Name) + ")") + " of ");
-						p.Parent.WriteTo(module, output, default);
+						var p = metadataFile.Metadata.GetGenericParameter(genericParamConstraint.Parameter);
+						output.Write("parameter " + p.Index + (p.Name.IsNil ? "" : " (" + metadataFile.Metadata.GetString(p.Name) + ")") + " of ");
+						p.Parent.WriteTo(metadataFile, output, default);
 						ownerTooltip = output.ToString();
 					}
 					return ownerTooltip;
@@ -115,19 +112,17 @@ public string OwnerTooltip {
 
 			public void OnTypeClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, genericParamConstraint.Type, protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, genericParamConstraint.Type, protocol: "metadata"));
 			}
 
 			string typeTooltip;
-			public string TypeTooltip => GenerateTooltip(ref typeTooltip, module, genericParamConstraint.Type);
+			public string TypeTooltip => GenerateTooltip(ref typeTooltip, metadataFile, genericParamConstraint.Type);
 
-			public GenericParamConstraintEntry(PEFile module, GenericParameterConstraintHandle handle)
+			public GenericParamConstraintEntry(MetadataFile metadataFile, GenericParameterConstraintHandle handle)
 			{
-				this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
-				this.module = module;
-				this.metadata = module.Metadata;
+				this.metadataFile = metadataFile;
 				this.handle = handle;
-				this.genericParamConstraint = metadata.GetGenericParameterConstraint(handle);
+				this.genericParamConstraint = metadataFile.Metadata.GetGenericParameterConstraint(handle);
 				this.ownerTooltip = null;
 				this.typeTooltip = null;
 			}
diff --git a/ILSpy/Metadata/CorTables/GenericParamTableTreeNode.cs b/ILSpy/Metadata/CorTables/GenericParamTableTreeNode.cs
index 789670a59f..7b88c771b9 100644
--- a/ILSpy/Metadata/CorTables/GenericParamTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/GenericParamTableTreeNode.cs
@@ -22,20 +22,18 @@
 using System.Reflection.Metadata.Ecma335;
 
 using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.Disassembler;
-using ICSharpCode.Decompiler.IL;
 using ICSharpCode.Decompiler.Metadata;
 
 namespace ICSharpCode.ILSpy.Metadata
 {
 	internal class GenericParamTableTreeNode : MetadataTableTreeNode
 	{
-		public GenericParamTableTreeNode(PEFile module)
-			: base(HandleKind.GenericParameter, module)
+		public GenericParamTableTreeNode(MetadataFile metadataFile)
+			: base(HandleKind.GenericParameter, metadataFile)
 		{
 		}
 
-		public override object Text => $"2A GenericParam ({module.Metadata.GetTableRowCount(TableIndex.GenericParam)})";
+		public override object Text => $"2A GenericParam ({metadataFile.Metadata.GetTableRowCount(TableIndex.GenericParam)})";
 
 		public override object Icon => Images.Literal;
 
@@ -49,9 +47,9 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			var list = new List<GenericParamEntry>();
 			GenericParamEntry scrollTargetEntry = default;
 
-			for (int row = 1; row <= module.Metadata.GetTableRowCount(TableIndex.GenericParam); row++)
+			for (int row = 1; row <= metadataFile.Metadata.GetTableRowCount(TableIndex.GenericParam); row++)
 			{
-				GenericParamEntry entry = new GenericParamEntry(module, MetadataTokens.GenericParameterHandle(row));
+				GenericParamEntry entry = new GenericParamEntry(metadataFile, MetadataTokens.GenericParameterHandle(row));
 				if (entry.RID == this.scrollTarget)
 				{
 					scrollTargetEntry = entry;
@@ -72,9 +70,7 @@ public override bool View(ViewModels.TabPageModel tabPage)
 
 		struct GenericParamEntry
 		{
-			readonly int metadataOffset;
-			readonly PEFile module;
-			readonly MetadataReader metadata;
+			readonly MetadataFile metadataFile;
 			readonly GenericParameterHandle handle;
 			readonly GenericParameter genericParam;
 
@@ -82,9 +78,9 @@ struct GenericParamEntry
 
 			public int Token => MetadataTokens.GetToken(handle);
 
-			public int Offset => metadataOffset
-				+ metadata.GetTableMetadataOffset(TableIndex.GenericParam)
-				+ metadata.GetTableRowSize(TableIndex.GenericParam) * (RID - 1);
+			public int Offset => metadataFile.MetadataOffset
+				+ metadataFile.Metadata.GetTableMetadataOffset(TableIndex.GenericParam)
+				+ metadataFile.Metadata.GetTableRowSize(TableIndex.GenericParam) * (RID - 1);
 
 			public int Number => genericParam.Index;
 
@@ -101,23 +97,21 @@ struct GenericParamEntry
 
 			public void OnOwnerClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, genericParam.Parent, protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, genericParam.Parent, protocol: "metadata"));
 			}
 
 			string ownerTooltip;
-			public string OwnerTooltip => GenerateTooltip(ref ownerTooltip, module, genericParam.Parent);
+			public string OwnerTooltip => GenerateTooltip(ref ownerTooltip, metadataFile, genericParam.Parent);
 
-			public string Name => metadata.GetString(genericParam.Name);
+			public string Name => metadataFile.Metadata.GetString(genericParam.Name);
 
 			public string NameTooltip => $"{MetadataTokens.GetHeapOffset(genericParam.Name):X} \"{Name}\"";
 
-			public GenericParamEntry(PEFile module, GenericParameterHandle handle)
+			public GenericParamEntry(MetadataFile metadataFile, GenericParameterHandle handle)
 			{
-				this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
-				this.module = module;
-				this.metadata = module.Metadata;
+				this.metadataFile = metadataFile;
 				this.handle = handle;
-				this.genericParam = metadata.GetGenericParameter(handle);
+				this.genericParam = metadataFile.Metadata.GetGenericParameter(handle);
 				this.ownerTooltip = null;
 			}
 		}
diff --git a/ILSpy/Metadata/CorTables/ImplMapTableTreeNode.cs b/ILSpy/Metadata/CorTables/ImplMapTableTreeNode.cs
index 9a7642b25e..a3aef6f7be 100644
--- a/ILSpy/Metadata/CorTables/ImplMapTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/ImplMapTableTreeNode.cs
@@ -23,8 +23,6 @@
 using System.Reflection.Metadata.Ecma335;
 
 using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.Disassembler;
-using ICSharpCode.Decompiler.IL;
 using ICSharpCode.Decompiler.Metadata;
 
 using Mono.Cecil;
@@ -33,12 +31,12 @@ namespace ICSharpCode.ILSpy.Metadata
 {
 	class ImplMapTableTreeNode : MetadataTableTreeNode
 	{
-		public ImplMapTableTreeNode(PEFile module)
-			: base((HandleKind)0x1C, module)
+		public ImplMapTableTreeNode(MetadataFile metadataFile)
+			: base((HandleKind)0x1C, metadataFile)
 		{
 		}
 
-		public override object Text => $"1C ImplMap ({module.Metadata.GetTableRowCount(TableIndex.ImplMap)})";
+		public override object Text => $"1C ImplMap ({metadataFile.Metadata.GetTableRowCount(TableIndex.ImplMap)})";
 
 		public override object Icon => Images.Literal;
 
@@ -50,17 +48,16 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			tabPage.SupportsLanguageSwitching = false;
 
 			var view = Helpers.PrepareDataGrid(tabPage, this);
-			var metadata = module.Metadata;
+			var metadata = metadataFile.Metadata;
 
 			var list = new List<ImplMapEntry>();
 			ImplMapEntry scrollTargetEntry = default;
 
 			var length = metadata.GetTableRowCount(TableIndex.ImplMap);
 			var span = metadata.AsReadOnlySpan();
-			int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
 			for (int rid = 1; rid <= length; rid++)
 			{
-				ImplMapEntry entry = new ImplMapEntry(module, span, metadataOffset, rid);
+				ImplMapEntry entry = new ImplMapEntry(metadataFile, span, rid);
 				if (entry.RID == this.scrollTarget)
 				{
 					scrollTargetEntry = entry;
@@ -98,8 +95,7 @@ public ImplMap(ReadOnlySpan<byte> span, int moduleRefSize, int memberForwardedTa
 
 		struct ImplMapEntry
 		{
-			readonly PEFile module;
-			readonly MetadataReader metadata;
+			readonly MetadataFile metadataFile;
 			readonly ImplMap implMap;
 
 			public int RID { get; }
@@ -124,38 +120,37 @@ struct ImplMapEntry
 
 			public void OnMemberForwardedClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, implMap.MemberForwarded, protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, implMap.MemberForwarded, protocol: "metadata"));
 			}
 
 			string memberForwardedTooltip;
-			public string MemberForwardedTooltip => GenerateTooltip(ref memberForwardedTooltip, module, implMap.MemberForwarded);
+			public string MemberForwardedTooltip => GenerateTooltip(ref memberForwardedTooltip, metadataFile, implMap.MemberForwarded);
 
 			[ColumnInfo("X8", Kind = ColumnKind.Token)]
 			public int ImportScope => MetadataTokens.GetToken(implMap.ImportScope);
 
 			public void OnImportScopeClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, implMap.ImportScope, protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, implMap.ImportScope, protocol: "metadata"));
 			}
 
 			string importScopeTooltip;
-			public string ImportScopeTooltip => GenerateTooltip(ref importScopeTooltip, module, implMap.ImportScope);
+			public string ImportScopeTooltip => GenerateTooltip(ref importScopeTooltip, metadataFile, implMap.ImportScope);
 
-			public string ImportName => metadata.GetString(implMap.ImportName);
+			public string ImportName => metadataFile.Metadata.GetString(implMap.ImportName);
 
 			public string ImportNameTooltip => $"{MetadataTokens.GetHeapOffset(implMap.ImportName):X} \"{ImportName}\"";
 
-			public ImplMapEntry(PEFile module, ReadOnlySpan<byte> span, int metadataOffset, int row)
+			public ImplMapEntry(MetadataFile metadataFile, ReadOnlySpan<byte> span, int row)
 			{
-				this.module = module;
-				this.metadata = module.Metadata;
+				this.metadataFile = metadataFile;
 				this.RID = row;
-				var rowOffset = metadata.GetTableMetadataOffset(TableIndex.ImplMap)
-					+ metadata.GetTableRowSize(TableIndex.ImplMap) * (row - 1);
-				this.Offset = metadataOffset + rowOffset;
-				int moduleRefSize = metadata.GetTableRowCount(TableIndex.ModuleRef) < ushort.MaxValue ? 2 : 4;
-				int memberForwardedTagRefSize = metadata.ComputeCodedTokenSize(32768, TableMask.MethodDef | TableMask.Field);
-				int stringHandleSize = metadata.GetHeapSize(HeapIndex.String) < ushort.MaxValue ? 2 : 4;
+				var rowOffset = metadataFile.Metadata.GetTableMetadataOffset(TableIndex.ImplMap)
+					+ metadataFile.Metadata.GetTableRowSize(TableIndex.ImplMap) * (row - 1);
+				this.Offset = metadataFile.MetadataOffset + rowOffset;
+				int moduleRefSize = metadataFile.Metadata.GetTableRowCount(TableIndex.ModuleRef) < ushort.MaxValue ? 2 : 4;
+				int memberForwardedTagRefSize = metadataFile.Metadata.ComputeCodedTokenSize(32768, TableMask.MethodDef | TableMask.Field);
+				int stringHandleSize = metadataFile.Metadata.GetHeapSize(HeapIndex.String) < ushort.MaxValue ? 2 : 4;
 				this.implMap = new ImplMap(span.Slice(rowOffset), moduleRefSize, memberForwardedTagRefSize, stringHandleSize);
 				this.importScopeTooltip = null;
 				this.memberForwardedTooltip = null;
diff --git a/ILSpy/Metadata/CorTables/InterfaceImplTableTreeNode.cs b/ILSpy/Metadata/CorTables/InterfaceImplTableTreeNode.cs
index e1ea243bfb..334616e364 100644
--- a/ILSpy/Metadata/CorTables/InterfaceImplTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/InterfaceImplTableTreeNode.cs
@@ -22,20 +22,18 @@
 using System.Reflection.Metadata.Ecma335;
 
 using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.Disassembler;
-using ICSharpCode.Decompiler.IL;
 using ICSharpCode.Decompiler.Metadata;
 
 namespace ICSharpCode.ILSpy.Metadata
 {
 	class InterfaceImplTableTreeNode : MetadataTableTreeNode
 	{
-		public InterfaceImplTableTreeNode(PEFile module)
-			: base((HandleKind)0x09, module)
+		public InterfaceImplTableTreeNode(MetadataFile metadataFile)
+			: base((HandleKind)0x09, metadataFile)
 		{
 		}
 
-		public override object Text => $"09 InterfaceImpl ({module.Metadata.GetTableRowCount(TableIndex.InterfaceImpl)})";
+		public override object Text => $"09 InterfaceImpl ({metadataFile.Metadata.GetTableRowCount(TableIndex.InterfaceImpl)})";
 
 		public override object Icon => Images.Literal;
 
@@ -45,17 +43,17 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			tabPage.SupportsLanguageSwitching = false;
 
 			var view = Helpers.PrepareDataGrid(tabPage, this);
-			var metadata = module.Metadata;
+			var metadata = metadataFile.Metadata;
 
 			var list = new List<InterfaceImplEntry>();
 			InterfaceImplEntry scrollTargetEntry = default;
 
 			var length = metadata.GetTableRowCount(TableIndex.InterfaceImpl);
 			ReadOnlySpan<byte> ptr = metadata.AsReadOnlySpan();
-			int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
+			int metadataOffset = metadataFile.MetadataOffset;
 			for (int rid = 1; rid <= length; rid++)
 			{
-				InterfaceImplEntry entry = new InterfaceImplEntry(module, ptr, metadataOffset, rid);
+				InterfaceImplEntry entry = new InterfaceImplEntry(metadataFile, ptr, rid);
 				if (entry.RID == this.scrollTarget)
 				{
 					scrollTargetEntry = entry;
@@ -89,8 +87,7 @@ public InterfaceImpl(ReadOnlySpan<byte> ptr, int classSize, int interfaceSize)
 
 		struct InterfaceImplEntry
 		{
-			readonly PEFile module;
-			readonly MetadataReader metadata;
+			readonly MetadataFile metadataFile;
 			readonly InterfaceImpl interfaceImpl;
 
 			public int RID { get; }
@@ -104,32 +101,31 @@ struct InterfaceImplEntry
 
 			public void OnClassClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, interfaceImpl.Class, protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, interfaceImpl.Class, protocol: "metadata"));
 			}
 
 			string classTooltip;
-			public string ClassTooltip => GenerateTooltip(ref classTooltip, module, interfaceImpl.Class);
+			public string ClassTooltip => GenerateTooltip(ref classTooltip, metadataFile, interfaceImpl.Class);
 
 			[ColumnInfo("X8", Kind = ColumnKind.Token)]
 			public int Interface => MetadataTokens.GetToken(interfaceImpl.Interface);
 
 			public void OnInterfaceClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, interfaceImpl.Interface, protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, interfaceImpl.Interface, protocol: "metadata"));
 			}
 
 			string interfaceTooltip;
-			public string InterfaceTooltip => GenerateTooltip(ref interfaceTooltip, module, interfaceImpl.Interface);
+			public string InterfaceTooltip => GenerateTooltip(ref interfaceTooltip, metadataFile, interfaceImpl.Interface);
 
-			public InterfaceImplEntry(PEFile module, ReadOnlySpan<byte> ptr, int metadataOffset, int row)
+			public InterfaceImplEntry(MetadataFile metadataFile, ReadOnlySpan<byte> ptr, int row)
 			{
-				this.module = module;
-				this.metadata = module.Metadata;
+				this.metadataFile = metadataFile;
 				this.RID = row;
-				var rowOffset = metadata.GetTableMetadataOffset(TableIndex.InterfaceImpl)
-					+ metadata.GetTableRowSize(TableIndex.InterfaceImpl) * (row - 1);
-				this.Offset = metadataOffset + rowOffset;
-				this.interfaceImpl = new InterfaceImpl(ptr.Slice(rowOffset), metadata.GetTableRowCount(TableIndex.TypeDef) < ushort.MaxValue ? 2 : 4, metadata.ComputeCodedTokenSize(16384, TableMask.TypeDef | TableMask.TypeRef | TableMask.TypeSpec));
+				var rowOffset = metadataFile.Metadata.GetTableMetadataOffset(TableIndex.InterfaceImpl)
+					+ metadataFile.Metadata.GetTableRowSize(TableIndex.InterfaceImpl) * (row - 1);
+				this.Offset = metadataFile.MetadataOffset + rowOffset;
+				this.interfaceImpl = new InterfaceImpl(ptr.Slice(rowOffset), metadataFile.Metadata.GetTableRowCount(TableIndex.TypeDef) < ushort.MaxValue ? 2 : 4, metadataFile.Metadata.ComputeCodedTokenSize(16384, TableMask.TypeDef | TableMask.TypeRef | TableMask.TypeSpec));
 				this.interfaceTooltip = null;
 				this.classTooltip = null;
 			}
diff --git a/ILSpy/Metadata/CorTables/ManifestResourceTableTreeNode.cs b/ILSpy/Metadata/CorTables/ManifestResourceTableTreeNode.cs
index 79fd5b76b0..997a8df436 100644
--- a/ILSpy/Metadata/CorTables/ManifestResourceTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/ManifestResourceTableTreeNode.cs
@@ -22,20 +22,18 @@
 using System.Reflection.Metadata.Ecma335;
 
 using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.Disassembler;
-using ICSharpCode.Decompiler.IL;
 using ICSharpCode.Decompiler.Metadata;
 
 namespace ICSharpCode.ILSpy.Metadata
 {
 	class ManifestResourceTableTreeNode : MetadataTableTreeNode
 	{
-		public ManifestResourceTableTreeNode(PEFile module)
-			: base(HandleKind.ManifestResource, module)
+		public ManifestResourceTableTreeNode(MetadataFile metadataFile)
+			: base(HandleKind.ManifestResource, metadataFile)
 		{
 		}
 
-		public override object Text => $"28 ManifestResource ({module.Metadata.GetTableRowCount(TableIndex.ManifestResource)})";
+		public override object Text => $"28 ManifestResource ({metadataFile.Metadata.GetTableRowCount(TableIndex.ManifestResource)})";
 
 		public override object Icon => Images.Literal;
 
@@ -45,14 +43,14 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			tabPage.SupportsLanguageSwitching = false;
 
 			var view = Helpers.PrepareDataGrid(tabPage, this);
-			var metadata = module.Metadata;
+			var metadata = metadataFile.Metadata;
 
 			var list = new List<ManifestResourceEntry>();
 			ManifestResourceEntry scrollTargetEntry = default;
 
 			foreach (var row in metadata.ManifestResources)
 			{
-				ManifestResourceEntry entry = new ManifestResourceEntry(module, row);
+				ManifestResourceEntry entry = new ManifestResourceEntry(metadataFile, row);
 				if (entry.RID == this.scrollTarget)
 				{
 					scrollTargetEntry = entry;
@@ -74,9 +72,7 @@ public override bool View(ViewModels.TabPageModel tabPage)
 
 		struct ManifestResourceEntry
 		{
-			readonly int metadataOffset;
-			readonly PEFile module;
-			readonly MetadataReader metadata;
+			readonly MetadataFile metadataFile;
 			readonly ManifestResourceHandle handle;
 			readonly ManifestResource manifestResource;
 
@@ -84,16 +80,16 @@ struct ManifestResourceEntry
 
 			public int Token => MetadataTokens.GetToken(handle);
 
-			public int Offset => metadataOffset
-				+ metadata.GetTableMetadataOffset(TableIndex.ManifestResource)
-				+ metadata.GetTableRowSize(TableIndex.ManifestResource) * (RID - 1);
+			public int Offset => metadataFile.MetadataOffset
+				+ metadataFile.Metadata.GetTableMetadataOffset(TableIndex.ManifestResource)
+				+ metadataFile.Metadata.GetTableRowSize(TableIndex.ManifestResource) * (RID - 1);
 
 			[ColumnInfo("X8", Kind = ColumnKind.Other)]
 			public ManifestResourceAttributes Attributes => manifestResource.Attributes;
 
 			public object AttributesTooltip => manifestResource.Attributes.ToString();
 
-			public string Name => metadata.GetString(manifestResource.Name);
+			public string Name => metadataFile.Metadata.GetString(manifestResource.Name);
 
 			public string NameTooltip => $"{MetadataTokens.GetHeapOffset(manifestResource.Name):X} \"{Name}\"";
 
@@ -102,19 +98,17 @@ struct ManifestResourceEntry
 
 			public void OnImplementationClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, manifestResource.Implementation, protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, manifestResource.Implementation, protocol: "metadata"));
 			}
 
 			string implementationTooltip;
-			public string ImplementationTooltip => GenerateTooltip(ref implementationTooltip, module, manifestResource.Implementation);
+			public string ImplementationTooltip => GenerateTooltip(ref implementationTooltip, metadataFile, manifestResource.Implementation);
 
-			public ManifestResourceEntry(PEFile module, ManifestResourceHandle handle)
+			public ManifestResourceEntry(MetadataFile metadataFile, ManifestResourceHandle handle)
 			{
-				this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
-				this.module = module;
-				this.metadata = module.Metadata;
+				this.metadataFile = metadataFile;
 				this.handle = handle;
-				this.manifestResource = metadata.GetManifestResource(handle);
+				this.manifestResource = metadataFile.Metadata.GetManifestResource(handle);
 				this.implementationTooltip = null;
 			}
 		}
diff --git a/ILSpy/Metadata/CorTables/MemberRefTableTreeNode.cs b/ILSpy/Metadata/CorTables/MemberRefTableTreeNode.cs
index 01e7806dce..1e0798292c 100644
--- a/ILSpy/Metadata/CorTables/MemberRefTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/MemberRefTableTreeNode.cs
@@ -21,20 +21,18 @@
 using System.Reflection.Metadata.Ecma335;
 
 using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.Disassembler;
-using ICSharpCode.Decompiler.IL;
 using ICSharpCode.Decompiler.Metadata;
 
 namespace ICSharpCode.ILSpy.Metadata
 {
 	internal class MemberRefTableTreeNode : MetadataTableTreeNode
 	{
-		public MemberRefTableTreeNode(PEFile module)
-			: base(HandleKind.MemberReference, module)
+		public MemberRefTableTreeNode(MetadataFile metadataFile)
+			: base(HandleKind.MemberReference, metadataFile)
 		{
 		}
 
-		public override object Text => $"0A MemberRef ({module.Metadata.GetTableRowCount(TableIndex.MemberRef)})";
+		public override object Text => $"0A MemberRef ({metadataFile.Metadata.GetTableRowCount(TableIndex.MemberRef)})";
 
 		public override object Icon => Images.Literal;
 
@@ -44,14 +42,14 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			tabPage.SupportsLanguageSwitching = false;
 
 			var view = Helpers.PrepareDataGrid(tabPage, this);
-			var metadata = module.Metadata;
+			var metadata = metadataFile.Metadata;
 
 			var list = new List<MemberRefEntry>();
 			MemberRefEntry scrollTargetEntry = default;
 
 			foreach (var row in metadata.MemberReferences)
 			{
-				MemberRefEntry entry = new MemberRefEntry(module, row);
+				MemberRefEntry entry = new MemberRefEntry(metadataFile, row);
 				if (entry.RID == this.scrollTarget)
 				{
 					scrollTargetEntry = entry;
@@ -73,9 +71,7 @@ public override bool View(ViewModels.TabPageModel tabPage)
 
 		struct MemberRefEntry
 		{
-			readonly int metadataOffset;
-			readonly PEFile module;
-			readonly MetadataReader metadata;
+			readonly MetadataFile metadataFile;
 			readonly MemberReferenceHandle handle;
 			readonly MemberReference memberRef;
 
@@ -83,22 +79,22 @@ struct MemberRefEntry
 
 			public int Token => MetadataTokens.GetToken(handle);
 
-			public int Offset => metadataOffset
-				+ metadata.GetTableMetadataOffset(TableIndex.MemberRef)
-				+ metadata.GetTableRowSize(TableIndex.MemberRef) * (RID - 1);
+			public int Offset => metadataFile.MetadataOffset
+				+ metadataFile.Metadata.GetTableMetadataOffset(TableIndex.MemberRef)
+				+ metadataFile.Metadata.GetTableRowSize(TableIndex.MemberRef) * (RID - 1);
 
 			[ColumnInfo("X8", Kind = ColumnKind.Token)]
 			public int Parent => MetadataTokens.GetToken(memberRef.Parent);
 
 			public void OnParentClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, memberRef.Parent, protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, memberRef.Parent, protocol: "metadata"));
 			}
 
 			string parentTooltip;
-			public string ParentTooltip => GenerateTooltip(ref parentTooltip, module, memberRef.Parent);
+			public string ParentTooltip => GenerateTooltip(ref parentTooltip, metadataFile, memberRef.Parent);
 
-			public string Name => metadata.GetString(memberRef.Name);
+			public string Name => metadataFile.Metadata.GetString(memberRef.Name);
 
 			public string NameTooltip => $"{MetadataTokens.GetHeapOffset(memberRef.Name):X} \"{Name}\"";
 
@@ -106,15 +102,13 @@ public void OnParentClick()
 			public int Signature => MetadataTokens.GetHeapOffset(memberRef.Signature);
 
 			string signatureTooltip;
-			public string SignatureTooltip => GenerateTooltip(ref signatureTooltip, module, handle);
+			public string SignatureTooltip => GenerateTooltip(ref signatureTooltip, metadataFile, handle);
 
-			public MemberRefEntry(PEFile module, MemberReferenceHandle handle)
+			public MemberRefEntry(MetadataFile metadataFile, MemberReferenceHandle handle)
 			{
-				this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
-				this.module = module;
-				this.metadata = module.Metadata;
+				this.metadataFile = metadataFile;
 				this.handle = handle;
-				this.memberRef = metadata.GetMemberReference(handle);
+				this.memberRef = metadataFile.Metadata.GetMemberReference(handle);
 				this.signatureTooltip = null;
 				this.parentTooltip = null;
 			}
diff --git a/ILSpy/Metadata/CorTables/MethodImplTableTreeNode.cs b/ILSpy/Metadata/CorTables/MethodImplTableTreeNode.cs
index 24b93afd00..21dc983636 100644
--- a/ILSpy/Metadata/CorTables/MethodImplTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/MethodImplTableTreeNode.cs
@@ -21,20 +21,18 @@
 using System.Reflection.Metadata.Ecma335;
 
 using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.Disassembler;
-using ICSharpCode.Decompiler.IL;
 using ICSharpCode.Decompiler.Metadata;
 
 namespace ICSharpCode.ILSpy.Metadata
 {
 	internal class MethodImplTableTreeNode : MetadataTableTreeNode
 	{
-		public MethodImplTableTreeNode(PEFile module)
-			: base((HandleKind)0x19, module)
+		public MethodImplTableTreeNode(MetadataFile metadataFile)
+			: base((HandleKind)0x19, metadataFile)
 		{
 		}
 
-		public override object Text => $"19 MethodImpl ({module.Metadata.GetTableRowCount(TableIndex.MethodImpl)})";
+		public override object Text => $"19 MethodImpl ({metadataFile.Metadata.GetTableRowCount(TableIndex.MethodImpl)})";
 
 		public override object Icon => Images.Literal;
 
@@ -48,9 +46,9 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			var list = new List<MethodImplEntry>();
 			MethodImplEntry scrollTargetEntry = default;
 
-			for (int row = 1; row <= module.Metadata.GetTableRowCount(TableIndex.MethodImpl); row++)
+			for (int row = 1; row <= metadataFile.Metadata.GetTableRowCount(TableIndex.MethodImpl); row++)
 			{
-				MethodImplEntry entry = new MethodImplEntry(module, MetadataTokens.MethodImplementationHandle(row));
+				MethodImplEntry entry = new MethodImplEntry(metadataFile, MetadataTokens.MethodImplementationHandle(row));
 				if (entry.RID == this.scrollTarget)
 				{
 					scrollTargetEntry = entry;
@@ -72,9 +70,7 @@ public override bool View(ViewModels.TabPageModel tabPage)
 
 		struct MethodImplEntry
 		{
-			readonly int metadataOffset;
-			readonly PEFile module;
-			readonly MetadataReader metadata;
+			readonly MetadataFile metadataFile;
 			readonly MethodImplementationHandle handle;
 			readonly MethodImplementation methodImpl;
 
@@ -82,50 +78,48 @@ struct MethodImplEntry
 
 			public int Token => MetadataTokens.GetToken(handle);
 
-			public int Offset => metadataOffset
-				+ metadata.GetTableMetadataOffset(TableIndex.MethodDef)
-				+ metadata.GetTableRowSize(TableIndex.MethodDef) * (RID - 1);
+			public int Offset => metadataFile.MetadataOffset
+				+ metadataFile.Metadata.GetTableMetadataOffset(TableIndex.MethodDef)
+				+ metadataFile.Metadata.GetTableRowSize(TableIndex.MethodDef) * (RID - 1);
 
 			[ColumnInfo("X8", Kind = ColumnKind.Token)]
 			public int MethodDeclaration => MetadataTokens.GetToken(methodImpl.MethodDeclaration);
 
 			public void OnMethodDeclarationClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, methodImpl.MethodDeclaration, protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, methodImpl.MethodDeclaration, protocol: "metadata"));
 			}
 
 			string methodDeclarationTooltip;
-			public string MethodDeclarationTooltip => GenerateTooltip(ref methodDeclarationTooltip, module, methodImpl.MethodDeclaration);
+			public string MethodDeclarationTooltip => GenerateTooltip(ref methodDeclarationTooltip, metadataFile, methodImpl.MethodDeclaration);
 
 			[ColumnInfo("X8", Kind = ColumnKind.Token)]
 			public int MethodBody => MetadataTokens.GetToken(methodImpl.MethodBody);
 
 			public void OnMethodBodyClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, methodImpl.MethodBody, protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, methodImpl.MethodBody, protocol: "metadata"));
 			}
 
 			string methodBodyTooltip;
-			public string MethodBodyTooltip => GenerateTooltip(ref methodBodyTooltip, module, methodImpl.MethodBody);
+			public string MethodBodyTooltip => GenerateTooltip(ref methodBodyTooltip, metadataFile, methodImpl.MethodBody);
 
 			[ColumnInfo("X8", Kind = ColumnKind.Token)]
 			public int Type => MetadataTokens.GetToken(methodImpl.Type);
 
 			public void OnTypeClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, methodImpl.Type, protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, methodImpl.Type, protocol: "metadata"));
 			}
 
 			string typeTooltip;
-			public string TypeTooltip => GenerateTooltip(ref typeTooltip, module, methodImpl.Type);
+			public string TypeTooltip => GenerateTooltip(ref typeTooltip, metadataFile, methodImpl.Type);
 
-			public MethodImplEntry(PEFile module, MethodImplementationHandle handle)
+			public MethodImplEntry(MetadataFile metadataFile, MethodImplementationHandle handle)
 			{
-				this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
-				this.module = module;
-				this.metadata = module.Metadata;
+				this.metadataFile = metadataFile;
 				this.handle = handle;
-				this.methodImpl = metadata.GetMethodImplementation(handle);
+				this.methodImpl = metadataFile.Metadata.GetMethodImplementation(handle);
 				this.typeTooltip = null;
 				this.methodBodyTooltip = null;
 				this.methodDeclarationTooltip = null;
diff --git a/ILSpy/Metadata/CorTables/MethodSemanticsTableTreeNode.cs b/ILSpy/Metadata/CorTables/MethodSemanticsTableTreeNode.cs
index 3f3ab38dfc..89277fd498 100644
--- a/ILSpy/Metadata/CorTables/MethodSemanticsTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/MethodSemanticsTableTreeNode.cs
@@ -22,20 +22,18 @@
 using System.Reflection.Metadata.Ecma335;
 
 using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.Disassembler;
-using ICSharpCode.Decompiler.IL;
 using ICSharpCode.Decompiler.Metadata;
 
 namespace ICSharpCode.ILSpy.Metadata
 {
 	internal class MethodSemanticsTableTreeNode : MetadataTableTreeNode
 	{
-		public MethodSemanticsTableTreeNode(PEFile module)
-			: base((HandleKind)0x18, module)
+		public MethodSemanticsTableTreeNode(MetadataFile metadataFile)
+			: base((HandleKind)0x18, metadataFile)
 		{
 		}
 
-		public override object Text => $"18 MethodSemantics ({module.Metadata.GetTableRowCount(TableIndex.MethodSemantics)})";
+		public override object Text => $"18 MethodSemantics ({metadataFile.Metadata.GetTableRowCount(TableIndex.MethodSemantics)})";
 
 		public override object Icon => Images.Literal;
 
@@ -45,14 +43,13 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			tabPage.SupportsLanguageSwitching = false;
 
 			var view = Helpers.PrepareDataGrid(tabPage, this);
-			var metadata = module.Metadata;
 
 			var list = new List<MethodSemanticsEntry>();
 			MethodSemanticsEntry scrollTargetEntry = default;
 
-			foreach (var row in metadata.GetMethodSemantics())
+			foreach (var row in metadataFile.Metadata.GetMethodSemantics())
 			{
-				MethodSemanticsEntry entry = new MethodSemanticsEntry(module, row.Handle, row.Semantics, row.Method, row.Association);
+				MethodSemanticsEntry entry = new MethodSemanticsEntry(metadataFile, row.Handle, row.Semantics, row.Method, row.Association);
 				if (entry.RID == this.scrollTarget)
 				{
 					scrollTargetEntry = entry;
@@ -74,9 +71,7 @@ public override bool View(ViewModels.TabPageModel tabPage)
 
 		struct MethodSemanticsEntry
 		{
-			readonly int metadataOffset;
-			readonly PEFile module;
-			readonly MetadataReader metadata;
+			readonly MetadataFile metadataFile;
 			readonly Handle handle;
 			readonly MethodSemanticsAttributes semantics;
 			readonly MethodDefinitionHandle method;
@@ -86,9 +81,9 @@ struct MethodSemanticsEntry
 
 			public int Token => MetadataTokens.GetToken(handle);
 
-			public int Offset => metadataOffset
-				+ metadata.GetTableMetadataOffset(TableIndex.MethodDef)
-				+ metadata.GetTableRowSize(TableIndex.MethodDef) * (RID - 1);
+			public int Offset => metadataFile.MetadataOffset
+				+ metadataFile.Metadata.GetTableMetadataOffset(TableIndex.MethodDef)
+				+ metadataFile.Metadata.GetTableRowSize(TableIndex.MethodDef) * (RID - 1);
 
 			[ColumnInfo("X8", Kind = ColumnKind.Other)]
 			public MethodSemanticsAttributes Semantics => semantics;
@@ -100,28 +95,26 @@ struct MethodSemanticsEntry
 
 			public void OnMethodClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, method, protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, method, protocol: "metadata"));
 			}
 
 			string methodTooltip;
-			public string MethodTooltip => GenerateTooltip(ref methodTooltip, module, method);
+			public string MethodTooltip => GenerateTooltip(ref methodTooltip, metadataFile, method);
 
 			[ColumnInfo("X8", Kind = ColumnKind.Token)]
 			public int Association => MetadataTokens.GetToken(association);
 
 			public void OnAssociationClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, association, protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, association, protocol: "metadata"));
 			}
 
 			string associationTooltip;
-			public string AssociationTooltip => GenerateTooltip(ref associationTooltip, module, association);
+			public string AssociationTooltip => GenerateTooltip(ref associationTooltip, metadataFile, association);
 
-			public MethodSemanticsEntry(PEFile module, Handle handle, MethodSemanticsAttributes semantics, MethodDefinitionHandle method, EntityHandle association)
+			public MethodSemanticsEntry(MetadataFile metadataFile, Handle handle, MethodSemanticsAttributes semantics, MethodDefinitionHandle method, EntityHandle association)
 			{
-				this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
-				this.module = module;
-				this.metadata = module.Metadata;
+				this.metadataFile = metadataFile;
 				this.handle = handle;
 				this.semantics = semantics;
 				this.method = method;
diff --git a/ILSpy/Metadata/CorTables/MethodSpecTableTreeNode.cs b/ILSpy/Metadata/CorTables/MethodSpecTableTreeNode.cs
index c050dbc58a..571b90414c 100644
--- a/ILSpy/Metadata/CorTables/MethodSpecTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/MethodSpecTableTreeNode.cs
@@ -22,19 +22,18 @@
 
 using ICSharpCode.Decompiler;
 using ICSharpCode.Decompiler.Disassembler;
-using ICSharpCode.Decompiler.IL;
 using ICSharpCode.Decompiler.Metadata;
 
 namespace ICSharpCode.ILSpy.Metadata
 {
 	internal class MethodSpecTableTreeNode : MetadataTableTreeNode
 	{
-		public MethodSpecTableTreeNode(PEFile module)
-			: base(HandleKind.MethodSpecification, module)
+		public MethodSpecTableTreeNode(MetadataFile metadataFile)
+			: base(HandleKind.MethodSpecification, metadataFile)
 		{
 		}
 
-		public override object Text => $"2B MethodSpec ({module.Metadata.GetTableRowCount(TableIndex.MethodSpec)})";
+		public override object Text => $"2B MethodSpec ({metadataFile.Metadata.GetTableRowCount(TableIndex.MethodSpec)})";
 
 		public override object Icon => Images.Literal;
 
@@ -44,14 +43,14 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			tabPage.SupportsLanguageSwitching = false;
 
 			var view = Helpers.PrepareDataGrid(tabPage, this);
-			var metadata = module.Metadata;
+			var metadata = metadataFile.Metadata;
 
 			var list = new List<MethodSpecEntry>();
 			MethodSpecEntry scrollTargetEntry = default;
 
 			foreach (var row in metadata.GetMethodSpecifications())
 			{
-				MethodSpecEntry entry = new MethodSpecEntry(module, row);
+				MethodSpecEntry entry = new MethodSpecEntry(metadataFile, row);
 				if (entry.RID == this.scrollTarget)
 				{
 					scrollTargetEntry = entry;
@@ -73,9 +72,7 @@ public override bool View(ViewModels.TabPageModel tabPage)
 
 		struct MethodSpecEntry
 		{
-			readonly int metadataOffset;
-			readonly PEFile module;
-			readonly MetadataReader metadata;
+			readonly MetadataFile metadataFile;
 			readonly MethodSpecificationHandle handle;
 			readonly MethodSpecification methodSpec;
 
@@ -83,20 +80,20 @@ struct MethodSpecEntry
 
 			public int Token => MetadataTokens.GetToken(handle);
 
-			public int Offset => metadataOffset
-				+ metadata.GetTableMetadataOffset(TableIndex.MethodSpec)
-				+ metadata.GetTableRowSize(TableIndex.MethodSpec) * (RID - 1);
+			public int Offset => metadataFile.MetadataOffset
+				+ metadataFile.Metadata.GetTableMetadataOffset(TableIndex.MethodSpec)
+				+ metadataFile.Metadata.GetTableRowSize(TableIndex.MethodSpec) * (RID - 1);
 
 			[ColumnInfo("X8", Kind = ColumnKind.Token)]
 			public int Method => MetadataTokens.GetToken(methodSpec.Method);
 
 			public void OnMethodClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, methodSpec.Method, protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, methodSpec.Method, protocol: "metadata"));
 			}
 
 			string methodTooltip;
-			public string MethodTooltip => GenerateTooltip(ref methodTooltip, module, methodSpec.Method);
+			public string MethodTooltip => GenerateTooltip(ref methodTooltip, metadataFile, methodSpec.Method);
 
 			[ColumnInfo("X8", Kind = ColumnKind.HeapOffset)]
 			public int Signature => MetadataTokens.GetHeapOffset(methodSpec.Signature);
@@ -104,7 +101,7 @@ public void OnMethodClick()
 			public string SignatureTooltip {
 				get {
 					ITextOutput output = new PlainTextOutput();
-					var signature = methodSpec.DecodeSignature(new DisassemblerSignatureTypeProvider(module, output), default);
+					var signature = methodSpec.DecodeSignature(new DisassemblerSignatureTypeProvider(metadataFile, output), default);
 					bool first = true;
 					foreach (var type in signature)
 					{
@@ -118,13 +115,11 @@ public string SignatureTooltip {
 				}
 			}
 
-			public MethodSpecEntry(PEFile module, MethodSpecificationHandle handle)
+			public MethodSpecEntry(MetadataFile metadataFile, MethodSpecificationHandle handle)
 			{
-				this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
-				this.module = module;
-				this.metadata = module.Metadata;
+				this.metadataFile = metadataFile;
 				this.handle = handle;
-				this.methodSpec = metadata.GetMethodSpecification(handle);
+				this.methodSpec = metadataFile.Metadata.GetMethodSpecification(handle);
 				this.methodTooltip = null;
 			}
 		}
diff --git a/ILSpy/Metadata/CorTables/MethodTableTreeNode.cs b/ILSpy/Metadata/CorTables/MethodTableTreeNode.cs
index d2a55ae612..2fc44383c2 100644
--- a/ILSpy/Metadata/CorTables/MethodTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/MethodTableTreeNode.cs
@@ -16,18 +16,13 @@
 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Reflection;
 using System.Reflection.Metadata;
 using System.Reflection.Metadata.Ecma335;
-using System.Windows.Controls;
-using System.Windows.Threading;
 
 using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.Disassembler;
-using ICSharpCode.Decompiler.IL;
 using ICSharpCode.Decompiler.Metadata;
 using ICSharpCode.Decompiler.TypeSystem;
 using ICSharpCode.ILSpy.TreeNodes;
@@ -36,12 +31,12 @@ namespace ICSharpCode.ILSpy.Metadata
 {
 	internal class MethodTableTreeNode : MetadataTableTreeNode
 	{
-		public MethodTableTreeNode(PEFile module)
-			: base(HandleKind.MethodDefinition, module)
+		public MethodTableTreeNode(MetadataFile metadataFile)
+			: base(HandleKind.MethodDefinition, metadataFile)
 		{
 		}
 
-		public override object Text => $"06 Method ({module.Metadata.GetTableRowCount(TableIndex.MethodDef)})";
+		public override object Text => $"06 Method ({metadataFile.Metadata.GetTableRowCount(TableIndex.MethodDef)})";
 
 		public override object Icon => Images.Literal;
 
@@ -51,13 +46,13 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			tabPage.SupportsLanguageSwitching = false;
 
 			var view = Helpers.PrepareDataGrid(tabPage, this);
-			var metadata = module.Metadata;
+			var metadata = metadataFile.Metadata;
 			var list = new List<MethodDefEntry>();
 			MethodDefEntry scrollTargetEntry = default;
 
 			foreach (var row in metadata.MethodDefinitions)
 			{
-				MethodDefEntry entry = new MethodDefEntry(module, row);
+				MethodDefEntry entry = new MethodDefEntry(metadataFile, row);
 				if (entry.RID == scrollTarget)
 				{
 					scrollTargetEntry = entry;
@@ -79,9 +74,7 @@ public override bool View(ViewModels.TabPageModel tabPage)
 
 		struct MethodDefEntry : IMemberTreeNode
 		{
-			readonly int metadataOffset;
-			readonly PEFile module;
-			readonly MetadataReader metadata;
+			readonly MetadataFile metadataFile;
 			readonly MethodDefinitionHandle handle;
 			readonly MethodDefinition methodDef;
 
@@ -89,9 +82,9 @@ struct MethodDefEntry : IMemberTreeNode
 
 			public int Token => MetadataTokens.GetToken(handle);
 
-			public int Offset => metadataOffset
-				+ metadata.GetTableMetadataOffset(TableIndex.MethodDef)
-				+ metadata.GetTableRowSize(TableIndex.MethodDef) * (RID - 1);
+			public int Offset => metadataFile.MetadataOffset
+				+ metadataFile.Metadata.GetTableMetadataOffset(TableIndex.MethodDef)
+				+ metadataFile.Metadata.GetTableRowSize(TableIndex.MethodDef) * (RID - 1);
 
 			[ColumnInfo("X8", Kind = ColumnKind.Other)]
 			public MethodAttributes Attributes => methodDef.Attributes;
@@ -114,7 +107,7 @@ struct MethodDefEntry : IMemberTreeNode
 
 			public int RVA => methodDef.RelativeVirtualAddress;
 
-			public string Name => metadata.GetString(methodDef.Name);
+			public string Name => metadataFile.Metadata.GetString(methodDef.Name);
 
 			public string NameTooltip => $"{MetadataTokens.GetHeapOffset(methodDef.Name):X} \"{Name}\"";
 
@@ -123,14 +116,14 @@ struct MethodDefEntry : IMemberTreeNode
 
 			string signatureTooltip;
 
-			public string SignatureTooltip => GenerateTooltip(ref signatureTooltip, module, handle);
+			public string SignatureTooltip => GenerateTooltip(ref signatureTooltip, metadataFile, handle);
 
 			[ColumnInfo("X8", Kind = ColumnKind.Token)]
 			public int ParamList => MetadataTokens.GetToken(methodDef.GetParameters().FirstOrDefault());
 
 			public void OnParamListClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, methodDef.GetParameters().FirstOrDefault(), protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, methodDef.GetParameters().FirstOrDefault(), protocol: "metadata"));
 			}
 
 			string paramListTooltip;
@@ -139,19 +132,17 @@ public string ParamListTooltip {
 					var param = methodDef.GetParameters().FirstOrDefault();
 					if (param.IsNil)
 						return null;
-					return GenerateTooltip(ref paramListTooltip, module, param);
+					return GenerateTooltip(ref paramListTooltip, metadataFile, param);
 				}
 			}
 
-			IEntity IMemberTreeNode.Member => ((MetadataModule)module.GetTypeSystemWithCurrentOptionsOrNull()?.MainModule).GetDefinition(handle);
+			IEntity IMemberTreeNode.Member => ((MetadataModule)metadataFile.GetTypeSystemWithCurrentOptionsOrNull()?.MainModule)?.GetDefinition(handle);
 
-			public MethodDefEntry(PEFile module, MethodDefinitionHandle handle)
+			public MethodDefEntry(MetadataFile metadataFile, MethodDefinitionHandle handle)
 			{
-				this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
-				this.module = module;
-				this.metadata = module.Metadata;
+				this.metadataFile = metadataFile;
 				this.handle = handle;
-				this.methodDef = metadata.GetMethodDefinition(handle);
+				this.methodDef = metadataFile.Metadata.GetMethodDefinition(handle);
 				this.signatureTooltip = null;
 				this.paramListTooltip = null;
 			}
diff --git a/ILSpy/Metadata/CorTables/ModuleRefTableTreeNode.cs b/ILSpy/Metadata/CorTables/ModuleRefTableTreeNode.cs
index 987471e855..26f63a88c0 100644
--- a/ILSpy/Metadata/CorTables/ModuleRefTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/ModuleRefTableTreeNode.cs
@@ -27,12 +27,12 @@ namespace ICSharpCode.ILSpy.Metadata
 {
 	internal class ModuleRefTableTreeNode : MetadataTableTreeNode
 	{
-		public ModuleRefTableTreeNode(PEFile module)
-			: base(HandleKind.ModuleReference, module)
+		public ModuleRefTableTreeNode(MetadataFile metadataFile)
+			: base(HandleKind.ModuleReference, metadataFile)
 		{
 		}
 
-		public override object Text => $"1A ModuleRef ({module.Metadata.GetTableRowCount(TableIndex.ModuleRef)})";
+		public override object Text => $"1A ModuleRef ({metadataFile.Metadata.GetTableRowCount(TableIndex.ModuleRef)})";
 
 		public override object Icon => Images.Literal;
 
@@ -42,14 +42,14 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			tabPage.SupportsLanguageSwitching = false;
 
 			var view = Helpers.PrepareDataGrid(tabPage, this);
-			var metadata = module.Metadata;
+			var metadata = metadataFile.Metadata;
 
 			var list = new List<ModuleRefEntry>();
 			ModuleRefEntry scrollTargetEntry = default;
 
 			foreach (var row in metadata.GetModuleReferences())
 			{
-				ModuleRefEntry entry = new ModuleRefEntry(module, row);
+				ModuleRefEntry entry = new ModuleRefEntry(metadataFile, row);
 				if (entry.RID == this.scrollTarget)
 				{
 					scrollTargetEntry = entry;
@@ -71,9 +71,7 @@ public override bool View(ViewModels.TabPageModel tabPage)
 
 		struct ModuleRefEntry
 		{
-			readonly int metadataOffset;
-			readonly PEFile module;
-			readonly MetadataReader metadata;
+			readonly MetadataFile metadataFile;
 			readonly ModuleReferenceHandle handle;
 			readonly ModuleReference moduleRef;
 
@@ -81,21 +79,19 @@ struct ModuleRefEntry
 
 			public int Token => MetadataTokens.GetToken(handle);
 
-			public int Offset => metadataOffset
-				+ metadata.GetTableMetadataOffset(TableIndex.ModuleRef)
-				+ metadata.GetTableRowSize(TableIndex.ModuleRef) * (RID - 1);
+			public int Offset => metadataFile.MetadataOffset
+				+ metadataFile.Metadata.GetTableMetadataOffset(TableIndex.ModuleRef)
+				+ metadataFile.Metadata.GetTableRowSize(TableIndex.ModuleRef) * (RID - 1);
 
-			public string Name => metadata.GetString(moduleRef.Name);
+			public string Name => metadataFile.Metadata.GetString(moduleRef.Name);
 
 			public string NameTooltip => $"{MetadataTokens.GetHeapOffset(moduleRef.Name):X} \"{Name}\"";
 
-			public ModuleRefEntry(PEFile module, ModuleReferenceHandle handle)
+			public ModuleRefEntry(MetadataFile metadataFile, ModuleReferenceHandle handle)
 			{
-				this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
-				this.module = module;
-				this.metadata = module.Metadata;
+				this.metadataFile = metadataFile;
 				this.handle = handle;
-				this.moduleRef = metadata.GetModuleReference(handle);
+				this.moduleRef = metadataFile.Metadata.GetModuleReference(handle);
 			}
 		}
 
diff --git a/ILSpy/Metadata/CorTables/ModuleTableTreeNode.cs b/ILSpy/Metadata/CorTables/ModuleTableTreeNode.cs
index ba65094264..edc8af029b 100644
--- a/ILSpy/Metadata/CorTables/ModuleTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/ModuleTableTreeNode.cs
@@ -27,12 +27,12 @@ namespace ICSharpCode.ILSpy.Metadata
 {
 	internal class ModuleTableTreeNode : MetadataTableTreeNode
 	{
-		public ModuleTableTreeNode(PEFile module)
-			: base(HandleKind.ModuleDefinition, module)
+		public ModuleTableTreeNode(MetadataFile metadataFile)
+			: base(HandleKind.ModuleDefinition, metadataFile)
 		{
 		}
 
-		public override object Text => $"00 Module ({module.Metadata.GetTableRowCount(TableIndex.Module)})";
+		public override object Text => $"00 Module ({metadataFile.Metadata.GetTableRowCount(TableIndex.Module)})";
 
 		public override object Icon => Images.Literal;
 
@@ -46,7 +46,7 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			var list = new List<ModuleEntry>();
 			ModuleEntry scrollTargetEntry = default;
 
-			list.Add(new ModuleEntry(module, EntityHandle.ModuleDefinition));
+			list.Add(new ModuleEntry(metadataFile, EntityHandle.ModuleDefinition));
 
 			view.ItemsSource = list;
 
@@ -62,9 +62,7 @@ public override bool View(ViewModels.TabPageModel tabPage)
 
 		struct ModuleEntry
 		{
-			readonly int metadataOffset;
-			readonly PEFile module;
-			readonly MetadataReader metadata;
+			readonly MetadataFile metadataFile;
 			readonly ModuleDefinitionHandle handle;
 			readonly ModuleDefinition moduleDef;
 
@@ -72,38 +70,36 @@ struct ModuleEntry
 
 			public int Token => MetadataTokens.GetToken(handle);
 
-			public int Offset => metadataOffset
-				+ metadata.GetTableMetadataOffset(TableIndex.Module)
-				+ metadata.GetTableRowSize(TableIndex.Module) * (RID - 1);
+			public int Offset => metadataFile.MetadataOffset
+				+ metadataFile.Metadata.GetTableMetadataOffset(TableIndex.Module)
+				+ metadataFile.Metadata.GetTableRowSize(TableIndex.Module) * (RID - 1);
 
 			public int Generation => moduleDef.Generation;
 
-			public string Name => metadata.GetString(moduleDef.Name);
+			public string Name => metadataFile.Metadata.GetString(moduleDef.Name);
 
 			public string NameTooltip => $"{MetadataTokens.GetHeapOffset(moduleDef.Name):X} \"{Name}\"";
 
 			[ColumnInfo("X8", Kind = ColumnKind.HeapOffset)]
 			public int Mvid => MetadataTokens.GetHeapOffset(moduleDef.Mvid);
 
-			public string MvidTooltip => metadata.GetGuid(moduleDef.Mvid).ToString();
+			public string MvidTooltip => metadataFile.Metadata.GetGuid(moduleDef.Mvid).ToString();
 
 			[ColumnInfo("X8", Kind = ColumnKind.HeapOffset)]
 			public int GenerationId => MetadataTokens.GetHeapOffset(moduleDef.GenerationId);
 
-			public string GenerationIdTooltip => moduleDef.GenerationId.IsNil ? null : metadata.GetGuid(moduleDef.GenerationId).ToString();
+			public string GenerationIdTooltip => moduleDef.GenerationId.IsNil ? null : metadataFile.Metadata.GetGuid(moduleDef.GenerationId).ToString();
 
 			[ColumnInfo("X8", Kind = ColumnKind.HeapOffset)]
 			public int BaseGenerationId => MetadataTokens.GetHeapOffset(moduleDef.BaseGenerationId);
 
-			public string BaseGenerationIdTooltip => moduleDef.BaseGenerationId.IsNil ? null : metadata.GetGuid(moduleDef.BaseGenerationId).ToString();
+			public string BaseGenerationIdTooltip => moduleDef.BaseGenerationId.IsNil ? null : metadataFile.Metadata.GetGuid(moduleDef.BaseGenerationId).ToString();
 
-			public ModuleEntry(PEFile module, ModuleDefinitionHandle handle)
+			public ModuleEntry(MetadataFile metadataFile, ModuleDefinitionHandle handle)
 			{
-				this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
-				this.module = module;
-				this.metadata = module.Metadata;
+				this.metadataFile = metadataFile;
 				this.handle = handle;
-				this.moduleDef = metadata.GetModuleDefinition();
+				this.moduleDef = metadataFile.Metadata.GetModuleDefinition();
 			}
 		}
 
diff --git a/ILSpy/Metadata/CorTables/NestedClassTableTreeNode.cs b/ILSpy/Metadata/CorTables/NestedClassTableTreeNode.cs
index acdcaad8f5..a1fc91e8e1 100644
--- a/ILSpy/Metadata/CorTables/NestedClassTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/NestedClassTableTreeNode.cs
@@ -22,20 +22,18 @@
 using System.Reflection.Metadata.Ecma335;
 
 using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.Disassembler;
-using ICSharpCode.Decompiler.IL;
 using ICSharpCode.Decompiler.Metadata;
 
 namespace ICSharpCode.ILSpy.Metadata
 {
 	class NestedClassTableTreeNode : MetadataTableTreeNode
 	{
-		public NestedClassTableTreeNode(PEFile module)
-			: base((HandleKind)0x29, module)
+		public NestedClassTableTreeNode(MetadataFile metadataFile)
+			: base((HandleKind)0x29, metadataFile)
 		{
 		}
 
-		public override object Text => $"29 NestedClass ({module.Metadata.GetTableRowCount(TableIndex.NestedClass)})";
+		public override object Text => $"29 NestedClass ({metadataFile.Metadata.GetTableRowCount(TableIndex.NestedClass)})";
 
 		public override object Icon => Images.Literal;
 
@@ -45,17 +43,16 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			tabPage.SupportsLanguageSwitching = false;
 
 			var view = Helpers.PrepareDataGrid(tabPage, this);
-			var metadata = module.Metadata;
+			var metadata = metadataFile.Metadata;
 
 			var list = new List<NestedClassEntry>();
 			NestedClassEntry scrollTargetEntry = default;
 
 			var length = metadata.GetTableRowCount(TableIndex.NestedClass);
 			ReadOnlySpan<byte> ptr = metadata.AsReadOnlySpan();
-			int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
 			for (int rid = 1; rid <= length; rid++)
 			{
-				NestedClassEntry entry = new NestedClassEntry(module, ptr, metadataOffset, rid);
+				NestedClassEntry entry = new NestedClassEntry(metadataFile, ptr, rid);
 				if (entry.RID == this.scrollTarget)
 				{
 					scrollTargetEntry = entry;
@@ -89,8 +86,7 @@ public NestedClass(ReadOnlySpan<byte> ptr, int typeDefSize)
 
 		struct NestedClassEntry
 		{
-			readonly PEFile module;
-			readonly MetadataReader metadata;
+			readonly MetadataFile metadataFile;
 			readonly NestedClass nestedClass;
 
 			public int RID { get; }
@@ -104,32 +100,31 @@ struct NestedClassEntry
 
 			public void OnNestedClassClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, nestedClass.Nested, protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, nestedClass.Nested, protocol: "metadata"));
 			}
 
 			string nestedClassTooltip;
-			public string NestedClassTooltip => GenerateTooltip(ref nestedClassTooltip, module, nestedClass.Nested);
+			public string NestedClassTooltip => GenerateTooltip(ref nestedClassTooltip, metadataFile, nestedClass.Nested);
 
 			[ColumnInfo("X8", Kind = ColumnKind.Token)]
 			public int EnclosingClass => MetadataTokens.GetToken(nestedClass.Enclosing);
 
 			public void OnEnclosingClassClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, nestedClass.Enclosing, protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, nestedClass.Enclosing, protocol: "metadata"));
 			}
 
 			string enclosingClassTooltip;
-			public string EnclosingClassTooltip => GenerateTooltip(ref enclosingClassTooltip, module, nestedClass.Enclosing);
+			public string EnclosingClassTooltip => GenerateTooltip(ref enclosingClassTooltip, metadataFile, nestedClass.Enclosing);
 
-			public NestedClassEntry(PEFile module, ReadOnlySpan<byte> ptr, int metadataOffset, int row)
+			public NestedClassEntry(MetadataFile metadataFile, ReadOnlySpan<byte> ptr, int row)
 			{
-				this.module = module;
-				this.metadata = module.Metadata;
+				this.metadataFile = metadataFile;
 				this.RID = row;
-				var rowOffset = metadata.GetTableMetadataOffset(TableIndex.NestedClass)
-					+ metadata.GetTableRowSize(TableIndex.NestedClass) * (row - 1);
-				this.Offset = metadataOffset + rowOffset;
-				int typeDefSize = metadata.GetTableRowCount(TableIndex.TypeDef) < ushort.MaxValue ? 2 : 4;
+				var rowOffset = metadataFile.Metadata.GetTableMetadataOffset(TableIndex.NestedClass)
+					+ metadataFile.Metadata.GetTableRowSize(TableIndex.NestedClass) * (row - 1);
+				this.Offset = metadataFile.MetadataOffset + rowOffset;
+				int typeDefSize = metadataFile.Metadata.GetTableRowCount(TableIndex.TypeDef) < ushort.MaxValue ? 2 : 4;
 				this.nestedClass = new NestedClass(ptr.Slice(rowOffset), typeDefSize);
 				this.nestedClassTooltip = null;
 				this.enclosingClassTooltip = null;
diff --git a/ILSpy/Metadata/CorTables/ParamTableTreeNode.cs b/ILSpy/Metadata/CorTables/ParamTableTreeNode.cs
index 5fee320ee6..5c24f8bd5d 100644
--- a/ILSpy/Metadata/CorTables/ParamTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/ParamTableTreeNode.cs
@@ -28,12 +28,12 @@ namespace ICSharpCode.ILSpy.Metadata
 {
 	internal class ParamTableTreeNode : MetadataTableTreeNode
 	{
-		public ParamTableTreeNode(PEFile module)
-			: base(HandleKind.Parameter, module)
+		public ParamTableTreeNode(MetadataFile metadataFile)
+			: base(HandleKind.Parameter, metadataFile)
 		{
 		}
 
-		public override object Text => $"08 Param ({module.Metadata.GetTableRowCount(TableIndex.Param)})";
+		public override object Text => $"08 Param ({metadataFile.Metadata.GetTableRowCount(TableIndex.Param)})";
 
 		public override object Icon => Images.Literal;
 
@@ -47,9 +47,9 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			var list = new List<ParamEntry>();
 			ParamEntry scrollTargetEntry = default;
 
-			for (int row = 1; row <= module.Metadata.GetTableRowCount(TableIndex.Param); row++)
+			for (int row = 1; row <= metadataFile.Metadata.GetTableRowCount(TableIndex.Param); row++)
 			{
-				ParamEntry entry = new ParamEntry(module, MetadataTokens.ParameterHandle(row));
+				ParamEntry entry = new ParamEntry(metadataFile, MetadataTokens.ParameterHandle(row));
 				if (entry.RID == this.scrollTarget)
 				{
 					scrollTargetEntry = entry;
@@ -71,9 +71,7 @@ public override bool View(ViewModels.TabPageModel tabPage)
 
 		struct ParamEntry
 		{
-			readonly int metadataOffset;
-			readonly PEFile module;
-			readonly MetadataReader metadata;
+			readonly MetadataFile metadataFile;
 			readonly ParameterHandle handle;
 			readonly Parameter param;
 
@@ -81,9 +79,9 @@ struct ParamEntry
 
 			public int Token => MetadataTokens.GetToken(handle);
 
-			public int Offset => metadataOffset
-				+ metadata.GetTableMetadataOffset(TableIndex.Param)
-				+ metadata.GetTableRowSize(TableIndex.Param) * (RID - 1);
+			public int Offset => metadataFile.MetadataOffset
+				+ metadataFile.Metadata.GetTableMetadataOffset(TableIndex.Param)
+				+ metadataFile.Metadata.GetTableRowSize(TableIndex.Param) * (RID - 1);
 
 			[ColumnInfo("X8", Kind = ColumnKind.Other)]
 			public ParameterAttributes Attributes => param.Attributes;
@@ -92,19 +90,17 @@ struct ParamEntry
 				FlagGroup.CreateMultipleChoiceGroup(typeof(ParameterAttributes), selectedValue: (int)param.Attributes, includeAll: false)
 			};
 
-			public string Name => metadata.GetString(param.Name);
+			public string Name => metadataFile.Metadata.GetString(param.Name);
 
 			public string NameTooltip => $"{MetadataTokens.GetHeapOffset(param.Name):X} \"{Name}\"";
 
 			public int Sequence => param.SequenceNumber;
 
-			public ParamEntry(PEFile module, ParameterHandle handle)
+			public ParamEntry(MetadataFile metadataFile, ParameterHandle handle)
 			{
-				this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
-				this.module = module;
-				this.metadata = module.Metadata;
+				this.metadataFile = metadataFile;
 				this.handle = handle;
-				this.param = metadata.GetParameter(handle);
+				this.param = metadataFile.Metadata.GetParameter(handle);
 			}
 		}
 
diff --git a/ILSpy/Metadata/CorTables/PropertyMapTableTreeNode.cs b/ILSpy/Metadata/CorTables/PropertyMapTableTreeNode.cs
index d07b126c49..d3bbd2385e 100644
--- a/ILSpy/Metadata/CorTables/PropertyMapTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/PropertyMapTableTreeNode.cs
@@ -22,20 +22,18 @@
 using System.Reflection.Metadata.Ecma335;
 
 using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.Disassembler;
-using ICSharpCode.Decompiler.IL;
 using ICSharpCode.Decompiler.Metadata;
 
 namespace ICSharpCode.ILSpy.Metadata
 {
 	class PropertyMapTableTreeNode : MetadataTableTreeNode
 	{
-		public PropertyMapTableTreeNode(PEFile module)
-			: base((HandleKind)0x15, module)
+		public PropertyMapTableTreeNode(MetadataFile metadataFile)
+			: base((HandleKind)0x15, metadataFile)
 		{
 		}
 
-		public override object Text => $"15 PropertyMap ({module.Metadata.GetTableRowCount(TableIndex.PropertyMap)})";
+		public override object Text => $"15 PropertyMap ({metadataFile.Metadata.GetTableRowCount(TableIndex.PropertyMap)})";
 
 		public override object Icon => Images.Literal;
 
@@ -45,17 +43,16 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			tabPage.SupportsLanguageSwitching = false;
 
 			var view = Helpers.PrepareDataGrid(tabPage, this);
-			var metadata = module.Metadata;
+			var metadata = metadataFile.Metadata;
 
 			var list = new List<PropertyMapEntry>();
 			PropertyMapEntry scrollTargetEntry = default;
 
 			var length = metadata.GetTableRowCount(TableIndex.PropertyMap);
 			ReadOnlySpan<byte> ptr = metadata.AsReadOnlySpan();
-			int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
 			for (int rid = 1; rid <= length; rid++)
 			{
-				PropertyMapEntry entry = new PropertyMapEntry(module, ptr, metadataOffset, rid);
+				PropertyMapEntry entry = new PropertyMapEntry(metadataFile, ptr, rid);
 				if (entry.RID == this.scrollTarget)
 				{
 					scrollTargetEntry = entry;
@@ -89,8 +86,7 @@ public PropertyMap(ReadOnlySpan<byte> ptr, int typeDefSize, int propertyDefSize)
 
 		struct PropertyMapEntry
 		{
-			readonly PEFile module;
-			readonly MetadataReader metadata;
+			readonly MetadataFile metadataFile;
 			readonly PropertyMap propertyMap;
 
 			public int RID { get; }
@@ -104,33 +100,32 @@ struct PropertyMapEntry
 
 			public void OnParentClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, propertyMap.Parent, protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, propertyMap.Parent, protocol: "metadata"));
 			}
 
 			string parentTooltip;
-			public string ParentTooltip => GenerateTooltip(ref parentTooltip, module, propertyMap.Parent);
+			public string ParentTooltip => GenerateTooltip(ref parentTooltip, metadataFile, propertyMap.Parent);
 
 			[ColumnInfo("X8", Kind = ColumnKind.Token)]
 			public int PropertyList => MetadataTokens.GetToken(propertyMap.PropertyList);
 
 			public void OnPropertyListClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, propertyMap.PropertyList, protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, propertyMap.PropertyList, protocol: "metadata"));
 			}
 
 			string propertyListTooltip;
-			public string PropertyListTooltip => GenerateTooltip(ref propertyListTooltip, module, propertyMap.PropertyList);
+			public string PropertyListTooltip => GenerateTooltip(ref propertyListTooltip, metadataFile, propertyMap.PropertyList);
 
-			public PropertyMapEntry(PEFile module, ReadOnlySpan<byte> ptr, int metadataOffset, int row)
+			public PropertyMapEntry(MetadataFile metadataFile, ReadOnlySpan<byte> ptr, int row)
 			{
-				this.module = module;
-				this.metadata = module.Metadata;
+				this.metadataFile = metadataFile;
 				this.RID = row;
-				var rowOffset = metadata.GetTableMetadataOffset(TableIndex.PropertyMap)
-					+ metadata.GetTableRowSize(TableIndex.PropertyMap) * (row - 1);
-				this.Offset = metadataOffset + rowOffset;
-				int typeDefSize = metadata.GetTableRowCount(TableIndex.TypeDef) < ushort.MaxValue ? 2 : 4;
-				int propertyDefSize = metadata.GetTableRowCount(TableIndex.Property) < ushort.MaxValue ? 2 : 4;
+				var rowOffset = metadataFile.Metadata.GetTableMetadataOffset(TableIndex.PropertyMap)
+					+ metadataFile.Metadata.GetTableRowSize(TableIndex.PropertyMap) * (row - 1);
+				this.Offset = metadataFile.MetadataOffset + rowOffset;
+				int typeDefSize = metadataFile.Metadata.GetTableRowCount(TableIndex.TypeDef) < ushort.MaxValue ? 2 : 4;
+				int propertyDefSize = metadataFile.Metadata.GetTableRowCount(TableIndex.Property) < ushort.MaxValue ? 2 : 4;
 				this.propertyMap = new PropertyMap(ptr.Slice(rowOffset), typeDefSize, propertyDefSize);
 				this.propertyListTooltip = null;
 				this.parentTooltip = null;
diff --git a/ILSpy/Metadata/CorTables/PropertyTableTreeNode.cs b/ILSpy/Metadata/CorTables/PropertyTableTreeNode.cs
index 8240c2ac59..9419181ca3 100644
--- a/ILSpy/Metadata/CorTables/PropertyTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/PropertyTableTreeNode.cs
@@ -22,8 +22,6 @@
 using System.Reflection.Metadata.Ecma335;
 
 using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.Disassembler;
-using ICSharpCode.Decompiler.IL;
 using ICSharpCode.Decompiler.Metadata;
 using ICSharpCode.Decompiler.TypeSystem;
 using ICSharpCode.ILSpy.TreeNodes;
@@ -32,12 +30,12 @@ namespace ICSharpCode.ILSpy.Metadata
 {
 	internal class PropertyTableTreeNode : MetadataTableTreeNode
 	{
-		public PropertyTableTreeNode(PEFile module)
-			: base(HandleKind.PropertyDefinition, module)
+		public PropertyTableTreeNode(MetadataFile metadataFile)
+			: base(HandleKind.PropertyDefinition, metadataFile)
 		{
 		}
 
-		public override object Text => $"17 Property ({module.Metadata.GetTableRowCount(TableIndex.Property)})";
+		public override object Text => $"17 Property ({metadataFile.Metadata.GetTableRowCount(TableIndex.Property)})";
 
 		public override object Icon => Images.Literal;
 
@@ -47,14 +45,14 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			tabPage.SupportsLanguageSwitching = false;
 
 			var view = Helpers.PrepareDataGrid(tabPage, this);
-			var metadata = module.Metadata;
+			var metadata = metadataFile.Metadata;
 
 			var list = new List<PropertyDefEntry>();
 			PropertyDefEntry scrollTargetEntry = default;
 
 			foreach (var row in metadata.PropertyDefinitions)
 			{
-				PropertyDefEntry entry = new PropertyDefEntry(module, row);
+				PropertyDefEntry entry = new PropertyDefEntry(metadataFile, row);
 				if (entry.RID == this.scrollTarget)
 				{
 					scrollTargetEntry = entry;
@@ -76,9 +74,7 @@ public override bool View(ViewModels.TabPageModel tabPage)
 
 		struct PropertyDefEntry : IMemberTreeNode
 		{
-			readonly int metadataOffset;
-			readonly PEFile module;
-			readonly MetadataReader metadata;
+			readonly MetadataFile metadataFile;
 			readonly PropertyDefinitionHandle handle;
 			readonly PropertyDefinition propertyDef;
 
@@ -86,9 +82,9 @@ struct PropertyDefEntry : IMemberTreeNode
 
 			public int Token => MetadataTokens.GetToken(handle);
 
-			public int Offset => metadataOffset
-				+ metadata.GetTableMetadataOffset(TableIndex.Property)
-				+ metadata.GetTableRowSize(TableIndex.Property) * (RID - 1);
+			public int Offset => metadataFile.MetadataOffset
+				+ metadataFile.Metadata.GetTableMetadataOffset(TableIndex.Property)
+				+ metadataFile.Metadata.GetTableRowSize(TableIndex.Property) * (RID - 1);
 
 			[ColumnInfo("X8", Kind = ColumnKind.Other)]
 			public PropertyAttributes Attributes => propertyDef.Attributes;
@@ -97,25 +93,23 @@ struct PropertyDefEntry : IMemberTreeNode
 				FlagGroup.CreateMultipleChoiceGroup(typeof(PropertyAttributes), selectedValue: (int)propertyDef.Attributes, includeAll: false),
 			};
 
-			public string Name => metadata.GetString(propertyDef.Name);
+			public string Name => metadataFile.Metadata.GetString(propertyDef.Name);
 
 			public string NameTooltip => $"{MetadataTokens.GetHeapOffset(propertyDef.Name):X} \"{Name}\"";
 
-			IEntity IMemberTreeNode.Member => ((MetadataModule)module.GetTypeSystemWithCurrentOptionsOrNull()?.MainModule).GetDefinition(handle);
+			IEntity IMemberTreeNode.Member => ((MetadataModule)metadataFile.GetTypeSystemWithCurrentOptionsOrNull()?.MainModule).GetDefinition(handle);
 
 			[ColumnInfo("X8", Kind = ColumnKind.HeapOffset)]
 			public int Signature => MetadataTokens.GetHeapOffset(propertyDef.Signature);
 
 			string signatureTooltip;
-			public string SignatureTooltip => GenerateTooltip(ref signatureTooltip, module, handle);
+			public string SignatureTooltip => GenerateTooltip(ref signatureTooltip, metadataFile, handle);
 
-			public PropertyDefEntry(PEFile module, PropertyDefinitionHandle handle)
+			public PropertyDefEntry(MetadataFile metadataFile, PropertyDefinitionHandle handle)
 			{
-				this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
-				this.module = module;
-				this.metadata = module.Metadata;
+				this.metadataFile = metadataFile;
 				this.handle = handle;
-				this.propertyDef = metadata.GetPropertyDefinition(handle);
+				this.propertyDef = metadataFile.Metadata.GetPropertyDefinition(handle);
 				this.signatureTooltip = null;
 			}
 		}
diff --git a/ILSpy/Metadata/CorTables/StandAloneSigTableTreeNode.cs b/ILSpy/Metadata/CorTables/StandAloneSigTableTreeNode.cs
index 0e618aad21..08fba15791 100644
--- a/ILSpy/Metadata/CorTables/StandAloneSigTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/StandAloneSigTableTreeNode.cs
@@ -21,20 +21,18 @@
 using System.Reflection.Metadata.Ecma335;
 
 using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.Disassembler;
-using ICSharpCode.Decompiler.IL;
 using ICSharpCode.Decompiler.Metadata;
 
 namespace ICSharpCode.ILSpy.Metadata
 {
 	class StandAloneSigTableTreeNode : MetadataTableTreeNode
 	{
-		public StandAloneSigTableTreeNode(PEFile module)
-			: base(HandleKind.StandaloneSignature, module)
+		public StandAloneSigTableTreeNode(MetadataFile metadataFile)
+			: base(HandleKind.StandaloneSignature, metadataFile)
 		{
 		}
 
-		public override object Text => $"11 StandAloneSig ({module.Metadata.GetTableRowCount(TableIndex.StandAloneSig)})";
+		public override object Text => $"11 StandAloneSig ({metadataFile.Metadata.GetTableRowCount(TableIndex.StandAloneSig)})";
 
 		public override object Icon => Images.Literal;
 
@@ -48,9 +46,9 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			var list = new List<StandAloneSigEntry>();
 			StandAloneSigEntry scrollTargetEntry = default;
 
-			for (int row = 1; row <= module.Metadata.GetTableRowCount(TableIndex.StandAloneSig); row++)
+			for (int row = 1; row <= metadataFile.Metadata.GetTableRowCount(TableIndex.StandAloneSig); row++)
 			{
-				StandAloneSigEntry entry = new StandAloneSigEntry(module, MetadataTokens.StandaloneSignatureHandle(row));
+				StandAloneSigEntry entry = new StandAloneSigEntry(metadataFile, MetadataTokens.StandaloneSignatureHandle(row));
 				if (entry.RID == this.scrollTarget)
 				{
 					scrollTargetEntry = entry;
@@ -72,9 +70,7 @@ public override bool View(ViewModels.TabPageModel tabPage)
 
 		struct StandAloneSigEntry
 		{
-			readonly int metadataOffset;
-			readonly PEFile module;
-			readonly MetadataReader metadata;
+			readonly MetadataFile metadataFile;
 			readonly StandaloneSignatureHandle handle;
 			readonly StandaloneSignature standaloneSig;
 
@@ -82,23 +78,21 @@ struct StandAloneSigEntry
 
 			public int Token => MetadataTokens.GetToken(handle);
 
-			public int Offset => metadataOffset
-				+ metadata.GetTableMetadataOffset(TableIndex.StandAloneSig)
-				+ metadata.GetTableRowSize(TableIndex.StandAloneSig) * (RID - 1);
+			public int Offset => metadataFile.MetadataOffset
+				+ metadataFile.Metadata.GetTableMetadataOffset(TableIndex.StandAloneSig)
+				+ metadataFile.Metadata.GetTableRowSize(TableIndex.StandAloneSig) * (RID - 1);
 
 			[ColumnInfo("X8", Kind = ColumnKind.HeapOffset)]
 			public int Signature => MetadataTokens.GetHeapOffset(standaloneSig.Signature);
 
 			string signatureTooltip;
-			public string SignatureTooltip => GenerateTooltip(ref signatureTooltip, module, handle);
+			public string SignatureTooltip => GenerateTooltip(ref signatureTooltip, metadataFile, handle);
 
-			public StandAloneSigEntry(PEFile module, StandaloneSignatureHandle handle)
+			public StandAloneSigEntry(MetadataFile metadataFile, StandaloneSignatureHandle handle)
 			{
-				this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
-				this.module = module;
-				this.metadata = module.Metadata;
+				this.metadataFile = metadataFile;
 				this.handle = handle;
-				this.standaloneSig = metadata.GetStandaloneSignature(handle);
+				this.standaloneSig = metadataFile.Metadata.GetStandaloneSignature(handle);
 				this.signatureTooltip = null;
 			}
 		}
diff --git a/ILSpy/Metadata/CorTables/TypeDefTableTreeNode.cs b/ILSpy/Metadata/CorTables/TypeDefTableTreeNode.cs
index 3388a244ae..b0b3ec3792 100644
--- a/ILSpy/Metadata/CorTables/TypeDefTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/TypeDefTableTreeNode.cs
@@ -24,7 +24,6 @@
 
 using ICSharpCode.Decompiler;
 using ICSharpCode.Decompiler.Disassembler;
-using ICSharpCode.Decompiler.IL;
 using ICSharpCode.Decompiler.Metadata;
 using ICSharpCode.Decompiler.TypeSystem;
 using ICSharpCode.ILSpy.TreeNodes;
@@ -33,12 +32,12 @@ namespace ICSharpCode.ILSpy.Metadata
 {
 	internal class TypeDefTableTreeNode : MetadataTableTreeNode
 	{
-		public TypeDefTableTreeNode(PEFile module)
-			: base(HandleKind.TypeDefinition, module)
+		public TypeDefTableTreeNode(MetadataFile metadataFile)
+			: base(HandleKind.TypeDefinition, metadataFile)
 		{
 		}
 
-		public override object Text => $"02 TypeDef ({module.Metadata.GetTableRowCount(TableIndex.TypeDef)})";
+		public override object Text => $"02 TypeDef ({metadataFile.Metadata.GetTableRowCount(TableIndex.TypeDef)})";
 
 		public override object Icon => Images.Literal;
 
@@ -48,14 +47,14 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			tabPage.SupportsLanguageSwitching = false;
 
 			var view = Helpers.PrepareDataGrid(tabPage, this);
-			var metadata = module.Metadata;
+			var metadata = metadataFile.Metadata;
 
 			var list = new List<TypeDefEntry>();
 			TypeDefEntry scrollTargetEntry = default;
 
 			foreach (var row in metadata.TypeDefinitions)
 			{
-				TypeDefEntry entry = new TypeDefEntry(module, row);
+				TypeDefEntry entry = new TypeDefEntry(metadataFile, row);
 				if (entry.RID == this.scrollTarget)
 				{
 					scrollTargetEntry = entry;
@@ -77,9 +76,7 @@ public override bool View(ViewModels.TabPageModel tabPage)
 
 		struct TypeDefEntry : IMemberTreeNode
 		{
-			readonly int metadataOffset;
-			readonly PEFile module;
-			readonly MetadataReader metadata;
+			readonly MetadataFile metadataFile;
 			readonly TypeDefinitionHandle handle;
 			readonly TypeDefinition typeDef;
 
@@ -87,9 +84,9 @@ struct TypeDefEntry : IMemberTreeNode
 
 			public int Token => MetadataTokens.GetToken(handle);
 
-			public int Offset => metadataOffset
-				+ metadata.GetTableMetadataOffset(TableIndex.TypeDef)
-				+ metadata.GetTableRowSize(TableIndex.TypeDef) * (RID - 1);
+			public int Offset => metadataFile.MetadataOffset
+				+ metadataFile.Metadata.GetTableMetadataOffset(TableIndex.TypeDef)
+				+ metadataFile.Metadata.GetTableRowSize(TableIndex.TypeDef) * (RID - 1);
 
 			[ColumnInfo("X8", Kind = ColumnKind.Other)]
 			public TypeAttributes Attributes => typeDef.Attributes;
@@ -107,36 +104,36 @@ struct TypeDefEntry : IMemberTreeNode
 
 			public string NameTooltip => $"{MetadataTokens.GetHeapOffset(typeDef.Name):X} \"{Name}\"";
 
-			public string Name => metadata.GetString(typeDef.Name);
+			public string Name => metadataFile.Metadata.GetString(typeDef.Name);
 
 			public string NamespaceTooltip => $"{MetadataTokens.GetHeapOffset(typeDef.Namespace):X} \"{Namespace}\"";
 
-			public string Namespace => metadata.GetString(typeDef.Namespace);
+			public string Namespace => metadataFile.Metadata.GetString(typeDef.Namespace);
 
 			[ColumnInfo("X8", Kind = ColumnKind.Token)]
 			public int BaseType => MetadataTokens.GetToken(typeDef.BaseType);
 
 			public void OnBaseTypeClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, typeDef.BaseType, protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, typeDef.BaseType, protocol: "metadata"));
 			}
 
 			public string BaseTypeTooltip {
 				get {
 					var output = new PlainTextOutput();
-					var provider = new DisassemblerSignatureTypeProvider(module, output);
+					var provider = new DisassemblerSignatureTypeProvider(metadataFile, output);
 					if (typeDef.BaseType.IsNil)
 						return null;
 					switch (typeDef.BaseType.Kind)
 					{
 						case HandleKind.TypeDefinition:
-							provider.GetTypeFromDefinition(module.Metadata, (TypeDefinitionHandle)typeDef.BaseType, 0)(ILNameSyntax.Signature);
+							provider.GetTypeFromDefinition(metadataFile.Metadata, (TypeDefinitionHandle)typeDef.BaseType, 0)(ILNameSyntax.Signature);
 							return output.ToString();
 						case HandleKind.TypeReference:
-							provider.GetTypeFromReference(module.Metadata, (TypeReferenceHandle)typeDef.BaseType, 0)(ILNameSyntax.Signature);
+							provider.GetTypeFromReference(metadataFile.Metadata, (TypeReferenceHandle)typeDef.BaseType, 0)(ILNameSyntax.Signature);
 							return output.ToString();
 						case HandleKind.TypeSpecification:
-							provider.GetTypeFromSpecification(module.Metadata, new Decompiler.Metadata.MetadataGenericContext(default(TypeDefinitionHandle), module), (TypeSpecificationHandle)typeDef.BaseType, 0)(ILNameSyntax.Signature);
+							provider.GetTypeFromSpecification(metadataFile.Metadata, new Decompiler.Metadata.MetadataGenericContext(default(TypeDefinitionHandle), metadataFile.Metadata), (TypeSpecificationHandle)typeDef.BaseType, 0)(ILNameSyntax.Signature);
 							return output.ToString();
 						default:
 							return null;
@@ -149,7 +146,7 @@ public string BaseTypeTooltip {
 
 			public void OnFieldListClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, typeDef.GetFields().FirstOrDefault(), protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, typeDef.GetFields().FirstOrDefault(), protocol: "metadata"));
 			}
 
 			string fieldListTooltip;
@@ -158,7 +155,7 @@ public string FieldListTooltip {
 					var field = typeDef.GetFields().FirstOrDefault();
 					if (field.IsNil)
 						return null;
-					return GenerateTooltip(ref fieldListTooltip, module, field);
+					return GenerateTooltip(ref fieldListTooltip, metadataFile, field);
 				}
 			}
 
@@ -167,7 +164,7 @@ public string FieldListTooltip {
 
 			public void OnMethodListClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, typeDef.GetMethods().FirstOrDefault(), protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, typeDef.GetMethods().FirstOrDefault(), protocol: "metadata"));
 			}
 
 			string methodListTooltip;
@@ -176,19 +173,17 @@ public string MethodListTooltip {
 					var method = typeDef.GetMethods().FirstOrDefault();
 					if (method.IsNil)
 						return null;
-					return GenerateTooltip(ref methodListTooltip, module, method);
+					return GenerateTooltip(ref methodListTooltip, metadataFile, method);
 				}
 			}
 
-			IEntity IMemberTreeNode.Member => ((MetadataModule)module.GetTypeSystemWithCurrentOptionsOrNull()?.MainModule).GetDefinition(handle);
+			IEntity IMemberTreeNode.Member => ((MetadataModule)metadataFile.GetTypeSystemWithCurrentOptionsOrNull()?.MainModule).GetDefinition(handle);
 
-			public TypeDefEntry(PEFile module, TypeDefinitionHandle handle)
+			public TypeDefEntry(MetadataFile metadataFile, TypeDefinitionHandle handle)
 			{
-				this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
-				this.module = module;
-				this.metadata = module.Metadata;
+				this.metadataFile = metadataFile;
 				this.handle = handle;
-				this.typeDef = metadata.GetTypeDefinition(handle);
+				this.typeDef = metadataFile.Metadata.GetTypeDefinition(handle);
 				this.methodListTooltip = null;
 				this.fieldListTooltip = null;
 			}
diff --git a/ILSpy/Metadata/CorTables/TypeRefTableTreeNode.cs b/ILSpy/Metadata/CorTables/TypeRefTableTreeNode.cs
index f0a773dc3d..42dfd85fbe 100644
--- a/ILSpy/Metadata/CorTables/TypeRefTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/TypeRefTableTreeNode.cs
@@ -21,19 +21,18 @@
 using System.Reflection.Metadata.Ecma335;
 
 using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.IL;
 using ICSharpCode.Decompiler.Metadata;
 
 namespace ICSharpCode.ILSpy.Metadata
 {
 	internal class TypeRefTableTreeNode : MetadataTableTreeNode
 	{
-		public TypeRefTableTreeNode(PEFile module)
-			: base(HandleKind.TypeReference, module)
+		public TypeRefTableTreeNode(MetadataFile metadataFile)
+			: base(HandleKind.TypeReference, metadataFile)
 		{
 		}
 
-		public override object Text => $"01 TypeRef ({module.Metadata.GetTableRowCount(TableIndex.TypeRef)})";
+		public override object Text => $"01 TypeRef ({metadataFile.Metadata.GetTableRowCount(TableIndex.TypeRef)})";
 
 		public override object Icon => Images.Literal;
 
@@ -43,14 +42,14 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			tabPage.SupportsLanguageSwitching = false;
 
 			var view = Helpers.PrepareDataGrid(tabPage, this);
-			var metadata = module.Metadata;
+			var metadata = metadataFile.Metadata;
 
 			var list = new List<TypeRefEntry>();
 			TypeRefEntry scrollTargetEntry = default;
 
 			foreach (var row in metadata.TypeReferences)
 			{
-				TypeRefEntry entry = new TypeRefEntry(module, row);
+				TypeRefEntry entry = new TypeRefEntry(metadataFile, row);
 				if (entry.RID == this.scrollTarget)
 				{
 					scrollTargetEntry = entry;
@@ -72,9 +71,7 @@ public override bool View(ViewModels.TabPageModel tabPage)
 
 		struct TypeRefEntry
 		{
-			readonly int metadataOffset;
-			readonly PEFile module;
-			readonly MetadataReader metadata;
+			readonly MetadataFile metadataFile;
 			readonly TypeReferenceHandle handle;
 			readonly TypeReference typeRef;
 
@@ -82,36 +79,34 @@ struct TypeRefEntry
 
 			public int Token => MetadataTokens.GetToken(handle);
 
-			public int Offset => metadataOffset
-				+ metadata.GetTableMetadataOffset(TableIndex.TypeRef)
-				+ metadata.GetTableRowSize(TableIndex.TypeRef) * (RID - 1);
+			public int Offset => metadataFile.MetadataOffset
+				+ metadataFile.Metadata.GetTableMetadataOffset(TableIndex.TypeRef)
+				+ metadataFile.Metadata.GetTableRowSize(TableIndex.TypeRef) * (RID - 1);
 
 			[ColumnInfo("X8", Kind = ColumnKind.Token)]
 			public int ResolutionScope => MetadataTokens.GetToken(typeRef.ResolutionScope);
 
 			public void OnResolutionScopeClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, typeRef.ResolutionScope, protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, typeRef.ResolutionScope, protocol: "metadata"));
 			}
 
 			string resolutionScopeTooltip;
-			public string ResolutionScopeTooltip => GenerateTooltip(ref resolutionScopeTooltip, module, typeRef.ResolutionScope);
+			public string ResolutionScopeTooltip => GenerateTooltip(ref resolutionScopeTooltip, metadataFile, typeRef.ResolutionScope);
 
 			public string NameTooltip => $"{MetadataTokens.GetHeapOffset(typeRef.Name):X} \"{Name}\"";
 
-			public string Name => metadata.GetString(typeRef.Name);
+			public string Name => metadataFile.Metadata.GetString(typeRef.Name);
 
 			public string NamespaceTooltip => $"{MetadataTokens.GetHeapOffset(typeRef.Namespace):X} \"{Namespace}\"";
 
-			public string Namespace => metadata.GetString(typeRef.Namespace);
+			public string Namespace => metadataFile.Metadata.GetString(typeRef.Namespace);
 
-			public TypeRefEntry(PEFile module, TypeReferenceHandle handle)
+			public TypeRefEntry(MetadataFile metadataFile, TypeReferenceHandle handle)
 			{
-				this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
-				this.module = module;
-				this.metadata = module.Metadata;
+				this.metadataFile = metadataFile;
 				this.handle = handle;
-				this.typeRef = metadata.GetTypeReference(handle);
+				this.typeRef = metadataFile.Metadata.GetTypeReference(handle);
 				this.resolutionScopeTooltip = null;
 			}
 		}
diff --git a/ILSpy/Metadata/CorTables/TypeSpecTableTreeNode.cs b/ILSpy/Metadata/CorTables/TypeSpecTableTreeNode.cs
index 5b87adaa13..b7e5f81df7 100644
--- a/ILSpy/Metadata/CorTables/TypeSpecTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/TypeSpecTableTreeNode.cs
@@ -28,12 +28,12 @@ namespace ICSharpCode.ILSpy.Metadata
 {
 	internal class TypeSpecTableTreeNode : MetadataTableTreeNode
 	{
-		public TypeSpecTableTreeNode(PEFile module)
-			: base(HandleKind.TypeSpecification, module)
+		public TypeSpecTableTreeNode(MetadataFile metadataFile)
+			: base(HandleKind.TypeSpecification, metadataFile)
 		{
 		}
 
-		public override object Text => $"1B TypeSpec ({module.Metadata.GetTableRowCount(TableIndex.TypeSpec)})";
+		public override object Text => $"1B TypeSpec ({metadataFile.Metadata.GetTableRowCount(TableIndex.TypeSpec)})";
 
 		public override object Icon => Images.Literal;
 
@@ -43,14 +43,14 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			tabPage.SupportsLanguageSwitching = false;
 
 			var view = Helpers.PrepareDataGrid(tabPage, this);
-			var metadata = module.Metadata;
+			var metadata = metadataFile.Metadata;
 
 			var list = new List<TypeSpecEntry>();
 			TypeSpecEntry scrollTargetEntry = default;
 
 			foreach (var row in metadata.GetTypeSpecifications())
 			{
-				TypeSpecEntry entry = new TypeSpecEntry(module, row);
+				TypeSpecEntry entry = new TypeSpecEntry(metadataFile, row);
 				if (scrollTarget.Equals(row))
 				{
 					scrollTargetEntry = entry;
@@ -73,7 +73,7 @@ public override bool View(ViewModels.TabPageModel tabPage)
 		struct TypeSpecEntry
 		{
 			readonly int metadataOffset;
-			readonly PEFile module;
+			readonly MetadataFile module;
 			readonly MetadataReader metadata;
 			readonly TypeSpecificationHandle handle;
 			readonly TypeSpecification typeSpec;
@@ -97,11 +97,11 @@ public string SignatureTooltip {
 				}
 			}
 
-			public TypeSpecEntry(PEFile module, TypeSpecificationHandle handle)
+			public TypeSpecEntry(MetadataFile metadataFile, TypeSpecificationHandle handle)
 			{
-				this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
-				this.module = module;
-				this.metadata = module.Metadata;
+				this.module = metadataFile;
+				this.metadataOffset = metadataFile.MetadataOffset;
+				this.metadata = metadataFile.Metadata;
 				this.handle = handle;
 				this.typeSpec = metadata.GetTypeSpecification(handle);
 			}
diff --git a/ILSpy/Metadata/DebugDirectoryTreeNode.cs b/ILSpy/Metadata/DebugDirectoryTreeNode.cs
index 78e3704c17..93cfe2592e 100644
--- a/ILSpy/Metadata/DebugDirectoryTreeNode.cs
+++ b/ILSpy/Metadata/DebugDirectoryTreeNode.cs
@@ -18,15 +18,11 @@
 
 #nullable enable
 
-using System;
 using System.Collections.Generic;
 using System.Reflection.PortableExecutable;
-using System.Windows.Controls;
-using System.Windows.Data;
 
 using ICSharpCode.Decompiler;
 using ICSharpCode.Decompiler.Metadata;
-using ICSharpCode.ILSpy.TextView;
 using ICSharpCode.ILSpy.TreeNodes;
 
 namespace ICSharpCode.ILSpy.Metadata
@@ -79,7 +75,7 @@ protected override void LoadChildren()
 
 					case DebugDirectoryEntryType.EmbeddedPortablePdb:
 						var embeddedPortablePdbReader = module.Reader.ReadEmbeddedPortablePdbDebugDirectoryData(entry).GetMetadataReader();
-						this.Children.Add(new DebugMetadataTreeNode(module, isEmbedded: true, provider: embeddedPortablePdbReader));
+						this.Children.Add(new DebugMetadataTreeNode(module));
 						break;
 
 					case DebugDirectoryEntryType.PdbChecksum:
diff --git a/ILSpy/Metadata/DebugMetadataTablesTreeNode.cs b/ILSpy/Metadata/DebugMetadataTablesTreeNode.cs
index cc9f94c08f..0580e824f1 100644
--- a/ILSpy/Metadata/DebugMetadataTablesTreeNode.cs
+++ b/ILSpy/Metadata/DebugMetadataTablesTreeNode.cs
@@ -16,13 +16,10 @@
 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-using System.Collections.Generic;
-using System.Reflection.Metadata;
 using System.Reflection.Metadata.Ecma335;
 
 using ICSharpCode.Decompiler;
 using ICSharpCode.Decompiler.Metadata;
-using ICSharpCode.ILSpy.Options;
 using ICSharpCode.ILSpy.TreeNodes;
 using ICSharpCode.ILSpy.ViewModels;
 
@@ -30,15 +27,11 @@ namespace ICSharpCode.ILSpy.Metadata
 {
 	class DebugMetadataTablesTreeNode : ILSpyTreeNode
 	{
-		private PEFile module;
-		private bool isEmbedded;
-		private MetadataReader provider;
+		private MetadataFile metadataFile;
 
-		public DebugMetadataTablesTreeNode(PEFile module, bool isEmbedded, MetadataReader provider)
+		public DebugMetadataTablesTreeNode(MetadataFile metadataFile)
 		{
-			this.module = module;
-			this.isEmbedded = isEmbedded;
-			this.provider = provider;
+			this.metadataFile = metadataFile;
 			this.LazyLoading = true;
 		}
 
@@ -49,23 +42,23 @@ public DebugMetadataTablesTreeNode(PEFile module, bool isEmbedded, MetadataReade
 		protected override void LoadChildren()
 		{
 			if (ShowTable(TableIndex.Document))
-				this.Children.Add(new DocumentTableTreeNode(this.module, this.provider, isEmbedded));
+				this.Children.Add(new DocumentTableTreeNode(metadataFile));
 			if (ShowTable(TableIndex.MethodDebugInformation))
-				this.Children.Add(new MethodDebugInformationTableTreeNode(this.module, this.provider, isEmbedded));
+				this.Children.Add(new MethodDebugInformationTableTreeNode(metadataFile));
 			if (ShowTable(TableIndex.LocalScope))
-				this.Children.Add(new LocalScopeTableTreeNode(this.module, this.provider, isEmbedded));
+				this.Children.Add(new LocalScopeTableTreeNode(metadataFile));
 			if (ShowTable(TableIndex.LocalVariable))
-				this.Children.Add(new LocalVariableTableTreeNode(this.module, this.provider, isEmbedded));
+				this.Children.Add(new LocalVariableTableTreeNode(metadataFile));
 			if (ShowTable(TableIndex.LocalConstant))
-				this.Children.Add(new LocalConstantTableTreeNode(this.module, this.provider, isEmbedded));
+				this.Children.Add(new LocalConstantTableTreeNode(metadataFile));
 			if (ShowTable(TableIndex.ImportScope))
-				this.Children.Add(new ImportScopeTableTreeNode(this.module, this.provider, isEmbedded));
+				this.Children.Add(new ImportScopeTableTreeNode(metadataFile));
 			if (ShowTable(TableIndex.StateMachineMethod))
-				this.Children.Add(new StateMachineMethodTableTreeNode(this.module, this.provider, isEmbedded));
+				this.Children.Add(new StateMachineMethodTableTreeNode(metadataFile));
 			if (ShowTable(TableIndex.CustomDebugInformation))
-				this.Children.Add(new CustomDebugInformationTableTreeNode(this.module, this.provider, isEmbedded));
+				this.Children.Add(new CustomDebugInformationTableTreeNode(metadataFile));
 
-			bool ShowTable(TableIndex table) => !MainWindow.Instance.CurrentDisplaySettings.HideEmptyMetadataTables || this.provider.GetTableRowCount(table) > 0;
+			bool ShowTable(TableIndex table) => !MainWindow.Instance.CurrentDisplaySettings.HideEmptyMetadataTables || metadataFile.Metadata.GetTableRowCount(table) > 0;
 		}
 
 		public override bool View(TabPageModel tabPage)
diff --git a/ILSpy/Metadata/DebugMetadataTreeNode.cs b/ILSpy/Metadata/DebugMetadataTreeNode.cs
index cd140aa573..a6773ffd71 100644
--- a/ILSpy/Metadata/DebugMetadataTreeNode.cs
+++ b/ILSpy/Metadata/DebugMetadataTreeNode.cs
@@ -18,11 +18,9 @@
 
 using System.Linq;
 using System.Reflection.Metadata;
-using System.Reflection.Metadata.Ecma335;
 
 using ICSharpCode.Decompiler;
 using ICSharpCode.Decompiler.Metadata;
-using ICSharpCode.ILSpy.Options;
 using ICSharpCode.ILSpy.TreeNodes;
 using ICSharpCode.ILSpy.ViewModels;
 
@@ -30,16 +28,12 @@ namespace ICSharpCode.ILSpy.Metadata
 {
 	class DebugMetadataTreeNode : ILSpyTreeNode
 	{
-		private PEFile module;
-		private MetadataReader provider;
-		private bool isEmbedded;
+		private MetadataFile metadataFile;
 
-		public DebugMetadataTreeNode(PEFile module, bool isEmbedded, MetadataReader provider)
+		public DebugMetadataTreeNode(MetadataFile metadataFile)
 		{
-			this.module = module;
-			this.provider = provider;
-			this.isEmbedded = isEmbedded;
-			this.Text = "Debug Metadata (" + (isEmbedded ? "Embedded" : "From portable PDB") + ")";
+			this.metadataFile = metadataFile;
+			this.Text = "Debug Metadata (" + (metadataFile.IsEmbedded ? "Embedded" : "From portable PDB") + ")";
 			this.LazyLoading = true;
 		}
 
@@ -62,11 +56,11 @@ public override void Decompile(Language language, ITextOutput output, Decompilat
 
 		protected override void LoadChildren()
 		{
-			this.Children.Add(new DebugMetadataTablesTreeNode(module, this.isEmbedded, this.provider));
-			this.Children.Add(new StringHeapTreeNode(module, this.provider));
-			this.Children.Add(new UserStringHeapTreeNode(module, this.provider));
-			this.Children.Add(new GuidHeapTreeNode(module, this.provider));
-			this.Children.Add(new BlobHeapTreeNode(module, this.provider));
+			this.Children.Add(new DebugMetadataTablesTreeNode(metadataFile));
+			this.Children.Add(new StringHeapTreeNode(metadataFile));
+			this.Children.Add(new UserStringHeapTreeNode(metadataFile));
+			this.Children.Add(new GuidHeapTreeNode(metadataFile));
+			this.Children.Add(new BlobHeapTreeNode(metadataFile));
 		}
 
 		public MetadataTableTreeNode FindNodeByHandleKind(HandleKind kind)
diff --git a/ILSpy/Metadata/DebugTables/CustomDebugInformationTableTreeNode.cs b/ILSpy/Metadata/DebugTables/CustomDebugInformationTableTreeNode.cs
index 420232cafe..cf8224673f 100644
--- a/ILSpy/Metadata/DebugTables/CustomDebugInformationTableTreeNode.cs
+++ b/ILSpy/Metadata/DebugTables/CustomDebugInformationTableTreeNode.cs
@@ -19,33 +19,25 @@
 using System;
 using System.Collections;
 using System.Collections.Generic;
-using System.Reflection;
 using System.Reflection.Metadata;
 using System.Reflection.Metadata.Ecma335;
-using System.Text;
 using System.Windows;
 using System.Windows.Controls;
-using System.Windows.Data;
 
 using ICSharpCode.Decompiler;
 using ICSharpCode.Decompiler.DebugInfo;
-using ICSharpCode.Decompiler.Disassembler;
-using ICSharpCode.Decompiler.IL;
 using ICSharpCode.Decompiler.Metadata;
 
 namespace ICSharpCode.ILSpy.Metadata
 {
 	internal class CustomDebugInformationTableTreeNode : DebugMetadataTableTreeNode
 	{
-		private readonly bool isEmbedded;
-
-		public CustomDebugInformationTableTreeNode(PEFile module, MetadataReader metadata, bool isEmbedded)
-			: base(HandleKind.CustomDebugInformation, module, metadata)
+		public CustomDebugInformationTableTreeNode(MetadataFile metadataFile)
+			: base(HandleKind.CustomDebugInformation, metadataFile)
 		{
-			this.isEmbedded = isEmbedded;
 		}
 
-		public override object Text => $"37 CustomDebugInformation ({metadata.GetTableRowCount(TableIndex.CustomDebugInformation)})";
+		public override object Text => $"37 CustomDebugInformation ({metadataFile.Metadata.GetTableRowCount(TableIndex.CustomDebugInformation)})";
 
 		public override object Icon => Images.Literal;
 
@@ -62,9 +54,9 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			var list = new List<CustomDebugInformationEntry>();
 			CustomDebugInformationEntry scrollTargetEntry = default;
 
-			foreach (var row in metadata.CustomDebugInformation)
+			foreach (var row in metadataFile.Metadata.CustomDebugInformation)
 			{
-				CustomDebugInformationEntry entry = new CustomDebugInformationEntry(module, metadata, isEmbedded, row);
+				CustomDebugInformationEntry entry = new CustomDebugInformationEntry(metadataFile, row);
 				if (entry.RID == scrollTarget)
 				{
 					scrollTargetEntry = entry;
@@ -105,8 +97,7 @@ public override DataTemplate SelectTemplate(object item, DependencyObject contai
 		class CustomDebugInformationEntry
 		{
 			readonly int? offset;
-			readonly PEFile module;
-			readonly MetadataReader metadata;
+			readonly MetadataFile metadataFile;
 			readonly CustomDebugInformationHandle handle;
 			readonly CustomDebugInformation debugInfo;
 			internal readonly CustomDebugInformationKind kind;
@@ -202,11 +193,11 @@ static CustomDebugInformationKind GetKind(MetadataReader metadata, GuidHandle h)
 
 			public void OnParentClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, debugInfo.Parent, protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, debugInfo.Parent, protocol: "metadata"));
 			}
 
 			string parentTooltip;
-			public string ParentTooltip => GenerateTooltip(ref parentTooltip, module, debugInfo.Parent);
+			public string ParentTooltip => GenerateTooltip(ref parentTooltip, metadataFile, debugInfo.Parent);
 
 			string kindString;
 			public string Kind {
@@ -217,7 +208,7 @@ public string Kind {
 					Guid guid;
 					if (kind != CustomDebugInformationKind.None)
 					{
-						guid = metadata.GetGuid(debugInfo.Kind);
+						guid = metadataFile.Metadata.GetGuid(debugInfo.Kind);
 					}
 					else
 					{
@@ -251,7 +242,7 @@ public string ValueTooltip {
 				get {
 					if (debugInfo.Value.IsNil)
 						return "<nil>";
-					return metadata.GetBlobReader(debugInfo.Value).ToHexString();
+					return metadataFile.Metadata.GetBlobReader(debugInfo.Value).ToHexString();
 				}
 			}
 
@@ -265,7 +256,7 @@ public object RowDetails {
 					if (debugInfo.Value.IsNil)
 						return null;
 
-					var reader = metadata.GetBlobReader(debugInfo.Value);
+					var reader = metadataFile.Metadata.GetBlobReader(debugInfo.Value);
 					ArrayList list;
 
 					switch (kind)
@@ -324,15 +315,14 @@ public object RowDetails {
 				}
 			}
 
-			public CustomDebugInformationEntry(PEFile module, MetadataReader metadata, bool isEmbedded, CustomDebugInformationHandle handle)
+			public CustomDebugInformationEntry(MetadataFile metadataFile, CustomDebugInformationHandle handle)
 			{
-				this.offset = isEmbedded ? null : (int?)metadata.GetTableMetadataOffset(TableIndex.CustomDebugInformation)
-					+ metadata.GetTableRowSize(TableIndex.CustomDebugInformation) * (MetadataTokens.GetRowNumber(handle) - 1);
-				this.module = module;
-				this.metadata = metadata;
+				this.metadataFile = metadataFile;
+				this.offset = metadataFile.IsEmbedded ? null : (int?)metadataFile.Metadata.GetTableMetadataOffset(TableIndex.CustomDebugInformation)
+					+ metadataFile.Metadata.GetTableRowSize(TableIndex.CustomDebugInformation) * (MetadataTokens.GetRowNumber(handle) - 1);
 				this.handle = handle;
-				this.debugInfo = metadata.GetCustomDebugInformation(handle);
-				this.kind = GetKind(metadata, debugInfo.Kind);
+				this.debugInfo = metadataFile.Metadata.GetCustomDebugInformation(handle);
+				this.kind = GetKind(metadataFile.Metadata, debugInfo.Kind);
 			}
 		}
 
diff --git a/ILSpy/Metadata/DebugTables/DocumentTableTreeNode.cs b/ILSpy/Metadata/DebugTables/DocumentTableTreeNode.cs
index 2a7fdb8e4b..9a27eaa91e 100644
--- a/ILSpy/Metadata/DebugTables/DocumentTableTreeNode.cs
+++ b/ILSpy/Metadata/DebugTables/DocumentTableTreeNode.cs
@@ -18,7 +18,6 @@
 
 using System;
 using System.Collections.Generic;
-using System.Reflection;
 using System.Reflection.Metadata;
 using System.Reflection.Metadata.Ecma335;
 
@@ -30,15 +29,12 @@ namespace ICSharpCode.ILSpy.Metadata
 {
 	internal class DocumentTableTreeNode : DebugMetadataTableTreeNode
 	{
-		private readonly bool isEmbedded;
-
-		public DocumentTableTreeNode(PEFile module, MetadataReader metadata, bool isEmbedded)
-			: base(HandleKind.Document, module, metadata)
+		public DocumentTableTreeNode(MetadataFile metadataFile)
+			: base(HandleKind.Document, metadataFile)
 		{
-			this.isEmbedded = isEmbedded;
 		}
 
-		public override object Text => $"30 Document ({metadata.GetTableRowCount(TableIndex.Document)})";
+		public override object Text => $"30 Document ({metadataFile.Metadata.GetTableRowCount(TableIndex.Document)})";
 
 		public override object Icon => Images.Literal;
 
@@ -51,9 +47,9 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			var list = new List<DocumentEntry>();
 			DocumentEntry scrollTargetEntry = default;
 
-			foreach (var row in metadata.Documents)
+			foreach (var row in metadataFile.Metadata.Documents)
 			{
-				DocumentEntry entry = new DocumentEntry(metadata, isEmbedded, row);
+				DocumentEntry entry = new DocumentEntry(metadataFile, row);
 				if (entry.RID == scrollTarget)
 				{
 					scrollTargetEntry = entry;
@@ -73,10 +69,10 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			return true;
 		}
 
-		struct DocumentEntry
+		readonly struct DocumentEntry
 		{
 			readonly int? offset;
-			readonly MetadataReader metadata;
+			readonly MetadataFile metadataFile;
 			readonly DocumentHandle handle;
 			readonly Document document;
 
@@ -84,9 +80,9 @@ struct DocumentEntry
 
 			public int Token => MetadataTokens.GetToken(handle);
 
-			public object Offset => offset == null ? "n/a" : (object)offset;
+			public object Offset => offset == null ? "n/a" : offset;
 
-			public string Name => metadata.GetString(document.Name);
+			public string Name => metadataFile.Metadata.GetString(document.Name);
 
 			public string NameTooltip => $"{MetadataTokens.GetHeapOffset(document.Name):X} \"{Name}\"";
 
@@ -97,7 +93,7 @@ public string HashAlgorithmTooltip {
 				get {
 					if (document.HashAlgorithm.IsNil)
 						return null;
-					Guid guid = metadata.GetGuid(document.HashAlgorithm);
+					Guid guid = metadataFile.Metadata.GetGuid(document.HashAlgorithm);
 					if (guid == KnownGuids.HashAlgorithmSHA1)
 						return "SHA1 [ff1816ec-aa5e-4d10-87f7-6f4963833460]";
 					if (guid == KnownGuids.HashAlgorithmSHA256)
@@ -113,7 +109,7 @@ public string HashTooltip {
 				get {
 					if (document.Hash.IsNil)
 						return null;
-					System.Collections.Immutable.ImmutableArray<byte> token = metadata.GetBlobContent(document.Hash);
+					System.Collections.Immutable.ImmutableArray<byte> token = metadataFile.Metadata.GetBlobContent(document.Hash);
 					return token.ToHexString(token.Length);
 				}
 			}
@@ -125,7 +121,7 @@ public string LanguageTooltip {
 				get {
 					if (document.Language.IsNil)
 						return null;
-					Guid guid = metadata.GetGuid(document.Language);
+					Guid guid = metadataFile.Metadata.GetGuid(document.Language);
 					if (guid == KnownGuids.CSharpLanguageGuid)
 						return "Visual C# [3f5162f8-07c6-11d3-9053-00c04fa302a1]";
 					if (guid == KnownGuids.VBLanguageGuid)
@@ -136,13 +132,13 @@ public string LanguageTooltip {
 				}
 			}
 
-			public DocumentEntry(MetadataReader metadata, bool isEmbedded, DocumentHandle handle)
+			public DocumentEntry(MetadataFile metadataFile, DocumentHandle handle)
 			{
-				this.offset = isEmbedded ? null : (int?)metadata.GetTableMetadataOffset(TableIndex.Document)
-					+ metadata.GetTableRowSize(TableIndex.Document) * (MetadataTokens.GetRowNumber(handle) - 1);
-				this.metadata = metadata;
+				this.metadataFile = metadataFile;
+				this.offset = metadataFile.IsEmbedded ? null : (int?)metadataFile.Metadata.GetTableMetadataOffset(TableIndex.Document)
+					+ metadataFile.Metadata.GetTableRowSize(TableIndex.Document) * (MetadataTokens.GetRowNumber(handle) - 1);
 				this.handle = handle;
-				this.document = metadata.GetDocument(handle);
+				this.document = metadataFile.Metadata.GetDocument(handle);
 			}
 		}
 
diff --git a/ILSpy/Metadata/DebugTables/ImportScopeTableTreeNode.cs b/ILSpy/Metadata/DebugTables/ImportScopeTableTreeNode.cs
index 0e6ee99d0a..880d210455 100644
--- a/ILSpy/Metadata/DebugTables/ImportScopeTableTreeNode.cs
+++ b/ILSpy/Metadata/DebugTables/ImportScopeTableTreeNode.cs
@@ -16,32 +16,23 @@
 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-using System;
 using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
 using System.Reflection.Metadata;
 using System.Reflection.Metadata.Ecma335;
-using System.Text;
 
 using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.Disassembler;
-using ICSharpCode.Decompiler.IL;
 using ICSharpCode.Decompiler.Metadata;
 
 namespace ICSharpCode.ILSpy.Metadata
 {
 	internal class ImportScopeTableTreeNode : DebugMetadataTableTreeNode
 	{
-		private readonly bool isEmbedded;
-
-		public ImportScopeTableTreeNode(PEFile module, MetadataReader metadata, bool isEmbedded)
-			: base(HandleKind.ImportScope, module, metadata)
+		public ImportScopeTableTreeNode(MetadataFile metadataFile)
+			: base(HandleKind.ImportScope, metadataFile)
 		{
-			this.isEmbedded = isEmbedded;
 		}
 
-		public override object Text => $"35 ImportScope ({metadata.GetTableRowCount(TableIndex.ImportScope)})";
+		public override object Text => $"35 ImportScope ({metadataFile.Metadata.GetTableRowCount(TableIndex.ImportScope)})";
 
 		public override object Icon => Images.Literal;
 
@@ -54,9 +45,9 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			var list = new List<ImportScopeEntry>();
 			ImportScopeEntry scrollTargetEntry = default;
 
-			foreach (var row in metadata.ImportScopes)
+			foreach (var row in metadataFile.Metadata.ImportScopes)
 			{
-				ImportScopeEntry entry = new ImportScopeEntry(module, metadata, isEmbedded, row);
+				ImportScopeEntry entry = new ImportScopeEntry(metadataFile, row);
 				if (entry.RID == scrollTarget)
 				{
 					scrollTargetEntry = entry;
@@ -76,11 +67,10 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			return true;
 		}
 
-		struct ImportScopeEntry
+		readonly struct ImportScopeEntry
 		{
 			readonly int? offset;
-			readonly PEFile module;
-			readonly MetadataReader metadata;
+			readonly MetadataFile metadataFile;
 			readonly ImportScopeHandle handle;
 			readonly ImportScope localScope;
 
@@ -88,27 +78,26 @@ struct ImportScopeEntry
 
 			public int Token => MetadataTokens.GetToken(handle);
 
-			public object Offset => offset == null ? "n/a" : (object)offset;
+			public object Offset => offset == null ? "n/a" : offset;
 
 			[ColumnInfo("X8", Kind = ColumnKind.Token)]
 			public int Parent => MetadataTokens.GetToken(localScope.Parent);
 
 			public void OnParentClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, localScope.Parent, protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, localScope.Parent, protocol: "metadata"));
 			}
 
 			[ColumnInfo("X8", Kind = ColumnKind.HeapOffset)]
 			public int Imports => MetadataTokens.GetHeapOffset(localScope.ImportsBlob);
 
-			public ImportScopeEntry(PEFile module, MetadataReader metadata, bool isEmbedded, ImportScopeHandle handle)
+			public ImportScopeEntry(MetadataFile metadataFile, ImportScopeHandle handle)
 			{
-				this.offset = isEmbedded ? null : (int?)metadata.GetTableMetadataOffset(TableIndex.ImportScope)
-					+ metadata.GetTableRowSize(TableIndex.ImportScope) * (MetadataTokens.GetRowNumber(handle) - 1);
-				this.module = module;
-				this.metadata = metadata;
+				this.metadataFile = metadataFile;
 				this.handle = handle;
-				this.localScope = metadata.GetImportScope(handle);
+				this.localScope = metadataFile.Metadata.GetImportScope(handle);
+				this.offset = metadataFile.IsEmbedded ? null : (int?)metadataFile.Metadata.GetTableMetadataOffset(TableIndex.ImportScope)
+					+ metadataFile.Metadata.GetTableRowSize(TableIndex.ImportScope) * (MetadataTokens.GetRowNumber(handle) - 1);
 			}
 		}
 
diff --git a/ILSpy/Metadata/DebugTables/LocalConstantTableTreeNode.cs b/ILSpy/Metadata/DebugTables/LocalConstantTableTreeNode.cs
index 9eaf8be2af..7bfb14e529 100644
--- a/ILSpy/Metadata/DebugTables/LocalConstantTableTreeNode.cs
+++ b/ILSpy/Metadata/DebugTables/LocalConstantTableTreeNode.cs
@@ -16,30 +16,23 @@
 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-using System;
 using System.Collections.Generic;
-using System.Reflection;
 using System.Reflection.Metadata;
 using System.Reflection.Metadata.Ecma335;
-using System.Text;
 
 using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.Disassembler;
 using ICSharpCode.Decompiler.Metadata;
 
 namespace ICSharpCode.ILSpy.Metadata
 {
 	internal class LocalConstantTableTreeNode : DebugMetadataTableTreeNode
 	{
-		private readonly bool isEmbedded;
-
-		public LocalConstantTableTreeNode(PEFile module, MetadataReader metadata, bool isEmbedded)
-			: base(HandleKind.LocalConstant, module, metadata)
+		public LocalConstantTableTreeNode(MetadataFile metadataFile)
+			: base(HandleKind.LocalConstant, metadataFile)
 		{
-			this.isEmbedded = isEmbedded;
 		}
 
-		public override object Text => $"34 LocalConstant ({metadata.GetTableRowCount(TableIndex.LocalConstant)})";
+		public override object Text => $"34 LocalConstant ({metadataFile.Metadata.GetTableRowCount(TableIndex.LocalConstant)})";
 
 		public override object Icon => Images.Literal;
 
@@ -52,9 +45,9 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			var list = new List<LocalConstantEntry>();
 			LocalConstantEntry scrollTargetEntry = default;
 
-			foreach (var row in metadata.LocalConstants)
+			foreach (var row in metadataFile.Metadata.LocalConstants)
 			{
-				LocalConstantEntry entry = new LocalConstantEntry(module, metadata, isEmbedded, row);
+				LocalConstantEntry entry = new LocalConstantEntry(metadataFile, row);
 				if (entry.RID == scrollTarget)
 				{
 					scrollTargetEntry = entry;
@@ -77,8 +70,7 @@ public override bool View(ViewModels.TabPageModel tabPage)
 		struct LocalConstantEntry
 		{
 			readonly int? offset;
-			readonly PEFile module;
-			readonly MetadataReader metadata;
+			readonly MetadataFile metadataFile;
 			readonly LocalConstantHandle handle;
 			readonly LocalConstant localConst;
 
@@ -88,21 +80,20 @@ struct LocalConstantEntry
 
 			public object Offset => offset == null ? "n/a" : (object)offset;
 
-			public string Name => metadata.GetString(localConst.Name);
+			public string Name => metadataFile.Metadata.GetString(localConst.Name);
 
 			public string NameTooltip => $"{MetadataTokens.GetHeapOffset(localConst.Name):X} \"{Name}\"";
 
 			[ColumnInfo("X8", Kind = ColumnKind.HeapOffset)]
 			public int Signature => MetadataTokens.GetHeapOffset(localConst.Signature);
 
-			public LocalConstantEntry(PEFile module, MetadataReader metadata, bool isEmbedded, LocalConstantHandle handle)
+			public LocalConstantEntry(MetadataFile metadataFile, LocalConstantHandle handle)
 			{
-				this.offset = isEmbedded ? null : (int?)metadata.GetTableMetadataOffset(TableIndex.LocalConstant)
-					+ metadata.GetTableRowSize(TableIndex.LocalConstant) * (MetadataTokens.GetRowNumber(handle) - 1);
-				this.module = module;
-				this.metadata = metadata;
+				this.offset = metadataFile.IsEmbedded ? null : (int?)metadataFile.Metadata.GetTableMetadataOffset(TableIndex.LocalConstant)
+					+ metadataFile.Metadata.GetTableRowSize(TableIndex.LocalConstant) * (MetadataTokens.GetRowNumber(handle) - 1);
+				this.metadataFile = metadataFile;
 				this.handle = handle;
-				this.localConst = metadata.GetLocalConstant(handle);
+				this.localConst = metadataFile.Metadata.GetLocalConstant(handle);
 			}
 		}
 
diff --git a/ILSpy/Metadata/DebugTables/LocalScopeTableTreeNode.cs b/ILSpy/Metadata/DebugTables/LocalScopeTableTreeNode.cs
index 8b8ac8b1ab..e41c6caba6 100644
--- a/ILSpy/Metadata/DebugTables/LocalScopeTableTreeNode.cs
+++ b/ILSpy/Metadata/DebugTables/LocalScopeTableTreeNode.cs
@@ -16,32 +16,24 @@
 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-using System;
 using System.Collections.Generic;
 using System.Linq;
-using System.Reflection;
 using System.Reflection.Metadata;
 using System.Reflection.Metadata.Ecma335;
-using System.Text;
 
 using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.Disassembler;
-using ICSharpCode.Decompiler.IL;
 using ICSharpCode.Decompiler.Metadata;
 
 namespace ICSharpCode.ILSpy.Metadata
 {
 	internal class LocalScopeTableTreeNode : DebugMetadataTableTreeNode
 	{
-		private readonly bool isEmbedded;
-
-		public LocalScopeTableTreeNode(PEFile module, MetadataReader metadata, bool isEmbedded)
-			: base(HandleKind.LocalScope, module, metadata)
+		public LocalScopeTableTreeNode(MetadataFile metadataFile)
+			: base(HandleKind.LocalScope, metadataFile)
 		{
-			this.isEmbedded = isEmbedded;
 		}
 
-		public override object Text => $"32 LocalScope ({metadata.GetTableRowCount(TableIndex.LocalScope)})";
+		public override object Text => $"32 LocalScope ({metadataFile.Metadata.GetTableRowCount(TableIndex.LocalScope)})";
 
 		public override object Icon => Images.Literal;
 
@@ -54,9 +46,9 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			var list = new List<LocalScopeEntry>();
 			LocalScopeEntry scrollTargetEntry = default;
 
-			foreach (var row in metadata.LocalScopes)
+			foreach (var row in metadataFile.Metadata.LocalScopes)
 			{
-				LocalScopeEntry entry = new LocalScopeEntry(module, metadata, isEmbedded, row);
+				LocalScopeEntry entry = new LocalScopeEntry(metadataFile, row);
 				if (entry.RID == scrollTarget)
 				{
 					scrollTargetEntry = entry;
@@ -79,8 +71,7 @@ public override bool View(ViewModels.TabPageModel tabPage)
 		struct LocalScopeEntry
 		{
 			readonly int? offset;
-			readonly PEFile module;
-			readonly MetadataReader metadata;
+			readonly MetadataFile metadataFile;
 			readonly LocalScopeHandle handle;
 			readonly LocalScope localScope;
 
@@ -95,18 +86,18 @@ struct LocalScopeEntry
 
 			public void OnMethodClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, localScope.Method, protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, localScope.Method, protocol: "metadata"));
 			}
 
 			string methodTooltip;
-			public string MethodTooltip => GenerateTooltip(ref methodTooltip, module, localScope.Method);
+			public string MethodTooltip => GenerateTooltip(ref methodTooltip, metadataFile, localScope.Method);
 
 			[ColumnInfo("X8", Kind = ColumnKind.Token)]
 			public int ImportScope => MetadataTokens.GetToken(localScope.ImportScope);
 
 			public void OnImportScopeClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, localScope.ImportScope, protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, localScope.ImportScope, protocol: "metadata"));
 			}
 
 			[ColumnInfo("X8", Kind = ColumnKind.Token)]
@@ -114,7 +105,7 @@ public void OnImportScopeClick()
 
 			public void OnVariableListClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, localScope.GetLocalVariables().FirstOrDefault(), protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, localScope.GetLocalVariables().FirstOrDefault(), protocol: "metadata"));
 			}
 
 			[ColumnInfo("X8", Kind = ColumnKind.Token)]
@@ -122,21 +113,20 @@ public void OnVariableListClick()
 
 			public void OnConstantListClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, localScope.GetLocalConstants().FirstOrDefault(), protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, localScope.GetLocalConstants().FirstOrDefault(), protocol: "metadata"));
 			}
 
 			public int StartOffset => localScope.StartOffset;
 
 			public int Length => localScope.Length;
 
-			public LocalScopeEntry(PEFile module, MetadataReader metadata, bool isEmbedded, LocalScopeHandle handle)
+			public LocalScopeEntry(MetadataFile metadataFile, LocalScopeHandle handle)
 			{
-				this.offset = isEmbedded ? null : (int?)metadata.GetTableMetadataOffset(TableIndex.LocalScope)
-					+ metadata.GetTableRowSize(TableIndex.LocalScope) * (MetadataTokens.GetRowNumber(handle) - 1);
-				this.module = module;
-				this.metadata = metadata;
+				this.metadataFile = metadataFile;
+				this.offset = metadataFile.IsEmbedded ? null : (int?)metadataFile.Metadata.GetTableMetadataOffset(TableIndex.LocalScope)
+					+ metadataFile.Metadata.GetTableRowSize(TableIndex.LocalScope) * (MetadataTokens.GetRowNumber(handle) - 1);
 				this.handle = handle;
-				this.localScope = metadata.GetLocalScope(handle);
+				this.localScope = metadataFile.Metadata.GetLocalScope(handle);
 				this.methodTooltip = null;
 			}
 		}
diff --git a/ILSpy/Metadata/DebugTables/LocalVariableTableTreeNode.cs b/ILSpy/Metadata/DebugTables/LocalVariableTableTreeNode.cs
index 9913e1a6b5..17f0721e14 100644
--- a/ILSpy/Metadata/DebugTables/LocalVariableTableTreeNode.cs
+++ b/ILSpy/Metadata/DebugTables/LocalVariableTableTreeNode.cs
@@ -27,15 +27,12 @@ namespace ICSharpCode.ILSpy.Metadata
 {
 	internal class LocalVariableTableTreeNode : DebugMetadataTableTreeNode
 	{
-		private readonly bool isEmbedded;
-
-		public LocalVariableTableTreeNode(PEFile module, MetadataReader metadata, bool isEmbedded)
-			: base(HandleKind.LocalVariable, module, metadata)
+		public LocalVariableTableTreeNode(MetadataFile metadataFile)
+			: base(HandleKind.LocalVariable, metadataFile)
 		{
-			this.isEmbedded = isEmbedded;
 		}
 
-		public override object Text => $"33 LocalVariable ({metadata.GetTableRowCount(TableIndex.LocalVariable)})";
+		public override object Text => $"33 LocalVariable ({metadataFile.Metadata.GetTableRowCount(TableIndex.LocalVariable)})";
 
 		public override object Icon => Images.Literal;
 
@@ -48,9 +45,9 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			var list = new List<LocalVariableEntry>();
 			LocalVariableEntry scrollTargetEntry = default;
 
-			foreach (var row in metadata.LocalVariables)
+			foreach (var row in metadataFile.Metadata.LocalVariables)
 			{
-				LocalVariableEntry entry = new LocalVariableEntry(module, metadata, isEmbedded, row);
+				LocalVariableEntry entry = new LocalVariableEntry(metadataFile, row);
 				if (entry.RID == scrollTarget)
 				{
 					scrollTargetEntry = entry;
@@ -73,8 +70,7 @@ public override bool View(ViewModels.TabPageModel tabPage)
 		struct LocalVariableEntry
 		{
 			readonly int? offset;
-			readonly PEFile module;
-			readonly MetadataReader metadata;
+			readonly MetadataFile metadataFile;
 			readonly LocalVariableHandle handle;
 			readonly LocalVariable localVar;
 
@@ -93,18 +89,17 @@ struct LocalVariableEntry
 
 			public int Index => localVar.Index;
 
-			public string Name => metadata.GetString(localVar.Name);
+			public string Name => metadataFile.Metadata.GetString(localVar.Name);
 
 			public string NameTooltip => $"{MetadataTokens.GetHeapOffset(localVar.Name):X} \"{Name}\"";
 
-			public LocalVariableEntry(PEFile module, MetadataReader metadata, bool isEmbedded, LocalVariableHandle handle)
+			public LocalVariableEntry(MetadataFile metadataFile, LocalVariableHandle handle)
 			{
-				this.offset = isEmbedded ? null : (int?)metadata.GetTableMetadataOffset(TableIndex.LocalVariable)
-					+ metadata.GetTableRowSize(TableIndex.LocalVariable) * (MetadataTokens.GetRowNumber(handle) - 1);
-				this.module = module;
-				this.metadata = metadata;
+				this.metadataFile = metadataFile;
+				this.offset = metadataFile.IsEmbedded ? null : (int?)metadataFile.Metadata.GetTableMetadataOffset(TableIndex.LocalVariable)
+					+ metadataFile.Metadata.GetTableRowSize(TableIndex.LocalVariable) * (MetadataTokens.GetRowNumber(handle) - 1);
 				this.handle = handle;
-				this.localVar = metadata.GetLocalVariable(handle);
+				this.localVar = metadataFile.Metadata.GetLocalVariable(handle);
 			}
 		}
 
diff --git a/ILSpy/Metadata/DebugTables/MethodDebugInformationTableTreeNode.cs b/ILSpy/Metadata/DebugTables/MethodDebugInformationTableTreeNode.cs
index d439308e44..06b56e62af 100644
--- a/ILSpy/Metadata/DebugTables/MethodDebugInformationTableTreeNode.cs
+++ b/ILSpy/Metadata/DebugTables/MethodDebugInformationTableTreeNode.cs
@@ -16,9 +16,7 @@
 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-using System;
 using System.Collections.Generic;
-using System.Reflection;
 using System.Reflection.Metadata;
 using System.Reflection.Metadata.Ecma335;
 using System.Text;
@@ -31,15 +29,12 @@ namespace ICSharpCode.ILSpy.Metadata
 {
 	internal class MethodDebugInformationTableTreeNode : DebugMetadataTableTreeNode
 	{
-		private readonly bool isEmbedded;
-
-		public MethodDebugInformationTableTreeNode(PEFile module, MetadataReader metadata, bool isEmbedded)
-			: base(HandleKind.MethodDebugInformation, module, metadata)
+		public MethodDebugInformationTableTreeNode(MetadataFile metadataFile)
+			: base(HandleKind.MethodDebugInformation, metadataFile)
 		{
-			this.isEmbedded = isEmbedded;
 		}
 
-		public override object Text => $"31 MethodDebugInformation ({metadata.GetTableRowCount(TableIndex.MethodDebugInformation)})";
+		public override object Text => $"31 MethodDebugInformation ({metadataFile.Metadata.GetTableRowCount(TableIndex.MethodDebugInformation)})";
 
 		public override object Icon => Images.Literal;
 
@@ -52,9 +47,9 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			var list = new List<MethodDebugInformationEntry>();
 			MethodDebugInformationEntry scrollTargetEntry = default;
 
-			foreach (var row in metadata.MethodDebugInformation)
+			foreach (var row in metadataFile.Metadata.MethodDebugInformation)
 			{
-				MethodDebugInformationEntry entry = new MethodDebugInformationEntry(module, metadata, isEmbedded, row);
+				MethodDebugInformationEntry entry = new MethodDebugInformationEntry(metadataFile, row);
 				if (entry.RID == scrollTarget)
 				{
 					scrollTargetEntry = entry;
@@ -77,8 +72,7 @@ public override bool View(ViewModels.TabPageModel tabPage)
 		struct MethodDebugInformationEntry
 		{
 			readonly int? offset;
-			readonly PEFile module;
-			readonly MetadataReader metadata;
+			readonly MetadataFile metadataFile;
 			readonly MethodDebugInformationHandle handle;
 			readonly MethodDebugInformation debugInfo;
 
@@ -93,15 +87,15 @@ struct MethodDebugInformationEntry
 
 			public void OnDocumentClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, debugInfo.Document, protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, debugInfo.Document, protocol: "metadata"));
 			}
 
 			public string DocumentTooltip {
 				get {
 					if (debugInfo.Document.IsNil)
 						return null;
-					var document = metadata.GetDocument(debugInfo.Document);
-					return $"{MetadataTokens.GetHeapOffset(document.Name):X} \"{metadata.GetString(document.Name)}\"";
+					var document = metadataFile.Metadata.GetDocument(debugInfo.Document);
+					return $"{MetadataTokens.GetHeapOffset(document.Name):X} \"{metadataFile.Metadata.GetString(document.Name)}\"";
 				}
 			}
 
@@ -126,7 +120,7 @@ public string SequencePointsTooltip {
 
 			public void OnLocalSignatureClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, debugInfo.LocalSignature, protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, debugInfo.LocalSignature, protocol: "metadata"));
 			}
 
 			public string LocalSignatureTooltip {
@@ -134,9 +128,9 @@ public string LocalSignatureTooltip {
 					if (debugInfo.LocalSignature.IsNil)
 						return null;
 					ITextOutput output = new PlainTextOutput();
-					var context = new MetadataGenericContext(default(TypeDefinitionHandle), metadata);
-					StandaloneSignature localSignature = module.Metadata.GetStandaloneSignature(debugInfo.LocalSignature);
-					var signatureDecoder = new DisassemblerSignatureTypeProvider(module, output);
+					var context = new MetadataGenericContext(default(TypeDefinitionHandle), metadataFile.Metadata);
+					StandaloneSignature localSignature = metadataFile.Metadata.GetStandaloneSignature(debugInfo.LocalSignature);
+					var signatureDecoder = new DisassemblerSignatureTypeProvider(metadataFile, output);
 					int index = 0;
 					foreach (var item in localSignature.DecodeLocalSignature(signatureDecoder, context))
 					{
@@ -150,14 +144,13 @@ public string LocalSignatureTooltip {
 				}
 			}
 
-			public MethodDebugInformationEntry(PEFile module, MetadataReader metadata, bool isEmbedded, MethodDebugInformationHandle handle)
+			public MethodDebugInformationEntry(MetadataFile metadataFile, MethodDebugInformationHandle handle)
 			{
-				this.offset = isEmbedded ? null : (int?)metadata.GetTableMetadataOffset(TableIndex.MethodDebugInformation)
-					+ metadata.GetTableRowSize(TableIndex.MethodDebugInformation) * (MetadataTokens.GetRowNumber(handle) - 1);
-				this.module = module;
-				this.metadata = metadata;
+				this.metadataFile = metadataFile;
+				this.offset = metadataFile.IsEmbedded ? null : (int?)metadataFile.Metadata.GetTableMetadataOffset(TableIndex.MethodDebugInformation)
+					+ metadataFile.Metadata.GetTableRowSize(TableIndex.MethodDebugInformation) * (MetadataTokens.GetRowNumber(handle) - 1);
 				this.handle = handle;
-				this.debugInfo = metadata.GetMethodDebugInformation(handle);
+				this.debugInfo = metadataFile.Metadata.GetMethodDebugInformation(handle);
 			}
 		}
 
diff --git a/ILSpy/Metadata/DebugTables/StateMachineMethodTableTreeNode.cs b/ILSpy/Metadata/DebugTables/StateMachineMethodTableTreeNode.cs
index f4a463e78d..8da97990a0 100644
--- a/ILSpy/Metadata/DebugTables/StateMachineMethodTableTreeNode.cs
+++ b/ILSpy/Metadata/DebugTables/StateMachineMethodTableTreeNode.cs
@@ -16,31 +16,23 @@
 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-using System;
 using System.Collections.Generic;
-using System.Reflection;
 using System.Reflection.Metadata;
 using System.Reflection.Metadata.Ecma335;
-using System.Text;
 
 using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.Disassembler;
-using ICSharpCode.Decompiler.IL;
 using ICSharpCode.Decompiler.Metadata;
 
 namespace ICSharpCode.ILSpy.Metadata
 {
 	internal class StateMachineMethodTableTreeNode : DebugMetadataTableTreeNode
 	{
-		readonly bool isEmbedded;
-
-		public StateMachineMethodTableTreeNode(PEFile module, MetadataReader metadata, bool isEmbedded)
-			: base((HandleKind)0x36, module, metadata)
+		public StateMachineMethodTableTreeNode(MetadataFile metadataFile)
+			: base((HandleKind)0x36, metadataFile)
 		{
-			this.isEmbedded = isEmbedded;
 		}
 
-		public override object Text => $"36 StateMachineMethod ({metadata.GetTableRowCount(TableIndex.StateMachineMethod)})";
+		public override object Text => $"36 StateMachineMethod ({metadataFile.Metadata.GetTableRowCount(TableIndex.StateMachineMethod)})";
 
 		public override object Icon => Images.Literal;
 
@@ -52,13 +44,13 @@ public override bool View(ViewModels.TabPageModel tabPage)
 			var view = Helpers.PrepareDataGrid(tabPage, this);
 			var list = new List<StateMachineMethodEntry>();
 			StateMachineMethodEntry scrollTargetEntry = default;
-			var length = metadata.GetTableRowCount(TableIndex.StateMachineMethod);
-			var reader = metadata.AsBlobReader();
-			reader.Offset = metadata.GetTableMetadataOffset(TableIndex.StateMachineMethod);
+			var length = metadataFile.Metadata.GetTableRowCount(TableIndex.StateMachineMethod);
+			var reader = metadataFile.Metadata.AsBlobReader();
+			reader.Offset = metadataFile.Metadata.GetTableMetadataOffset(TableIndex.StateMachineMethod);
 
 			for (int rid = 1; rid <= length; rid++)
 			{
-				StateMachineMethodEntry entry = new StateMachineMethodEntry(module, ref reader, isEmbedded, rid);
+				StateMachineMethodEntry entry = new StateMachineMethodEntry(metadataFile, ref reader, rid);
 				if (scrollTarget == rid)
 				{
 					scrollTargetEntry = entry;
@@ -81,8 +73,7 @@ public override bool View(ViewModels.TabPageModel tabPage)
 		struct StateMachineMethodEntry
 		{
 			readonly int? offset;
-			readonly PEFile module;
-			readonly MetadataReader metadata;
+			readonly MetadataFile metadataFile;
 			readonly MethodDefinitionHandle moveNextMethod;
 			readonly MethodDefinitionHandle kickoffMethod;
 
@@ -97,33 +88,32 @@ struct StateMachineMethodEntry
 
 			public void OnMoveNextMethodClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, moveNextMethod, protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, moveNextMethod, protocol: "metadata"));
 			}
 
 			string moveNextMethodTooltip;
-			public string MoveNextMethodTooltip => GenerateTooltip(ref moveNextMethodTooltip, module, moveNextMethod);
+			public string MoveNextMethodTooltip => GenerateTooltip(ref moveNextMethodTooltip, metadataFile, moveNextMethod);
 
 			[ColumnInfo("X8", Kind = ColumnKind.Token)]
 			public int KickoffMethod => MetadataTokens.GetToken(kickoffMethod);
 
 			public void OnKickofMethodClick()
 			{
-				MainWindow.Instance.JumpToReference(new EntityReference(module, kickoffMethod, protocol: "metadata"));
+				MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, kickoffMethod, protocol: "metadata"));
 			}
 
 			string kickoffMethodTooltip;
-			public string KickoffMethodTooltip => GenerateTooltip(ref kickoffMethodTooltip, module, kickoffMethod);
+			public string KickoffMethodTooltip => GenerateTooltip(ref kickoffMethodTooltip, metadataFile, kickoffMethod);
 
-			public StateMachineMethodEntry(PEFile module, ref BlobReader reader, bool isEmbedded, int row)
+			public StateMachineMethodEntry(MetadataFile metadataFile, ref BlobReader reader, int row)
 			{
-				this.module = module;
-				this.metadata = module.Metadata;
+				this.metadataFile = metadataFile;
 				this.RID = row;
-				int rowOffset = metadata.GetTableMetadataOffset(TableIndex.StateMachineMethod)
-					+ metadata.GetTableRowSize(TableIndex.StateMachineMethod) * (row - 1);
-				this.offset = isEmbedded ? null : (int?)rowOffset;
+				int rowOffset = metadataFile.Metadata.GetTableMetadataOffset(TableIndex.StateMachineMethod)
+					+ metadataFile.Metadata.GetTableRowSize(TableIndex.StateMachineMethod) * (row - 1);
+				this.offset = metadataFile.IsEmbedded ? null : (int?)rowOffset;
 
-				int methodDefSize = metadata.GetTableRowCount(TableIndex.MethodDef) < ushort.MaxValue ? 2 : 4;
+				int methodDefSize = metadataFile.Metadata.GetTableRowCount(TableIndex.MethodDef) < ushort.MaxValue ? 2 : 4;
 				this.moveNextMethod = MetadataTokens.MethodDefinitionHandle(methodDefSize == 2 ? reader.ReadInt16() : reader.ReadInt32());
 				this.kickoffMethod = MetadataTokens.MethodDefinitionHandle(methodDefSize == 2 ? reader.ReadInt16() : reader.ReadInt32());
 				this.kickoffMethodTooltip = null;
diff --git a/ILSpy/Metadata/Heaps/BlobHeapTreeNode.cs b/ILSpy/Metadata/Heaps/BlobHeapTreeNode.cs
index f439e9acda..e1aa423647 100644
--- a/ILSpy/Metadata/Heaps/BlobHeapTreeNode.cs
+++ b/ILSpy/Metadata/Heaps/BlobHeapTreeNode.cs
@@ -16,22 +16,13 @@
 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-using System;
-using System.Collections;
 using System.Collections.Generic;
-using System.Reflection;
 using System.Reflection.Metadata;
 using System.Reflection.Metadata.Ecma335;
-using System.Text;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Data;
 
 using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.DebugInfo;
-using ICSharpCode.Decompiler.Disassembler;
-using ICSharpCode.Decompiler.IL;
 using ICSharpCode.Decompiler.Metadata;
+using ICSharpCode.ILSpyX;
 
 namespace ICSharpCode.ILSpy.Metadata
 {
@@ -39,11 +30,12 @@ internal class BlobHeapTreeNode : MetadataHeapTreeNode
 	{
 		readonly List<BlobHeapEntry> list;
 
-		public BlobHeapTreeNode(PEFile module, MetadataReader metadata)
-			: base(HandleKind.Blob, module, metadata)
+		public BlobHeapTreeNode(MetadataFile metadataFile)
+			: base(HandleKind.Blob, metadataFile)
 		{
 			list = new List<BlobHeapEntry>();
 
+			var metadata = metadataFile.Metadata;
 			BlobHandle handle = MetadataTokens.BlobHandle(0);
 			do
 			{
diff --git a/ILSpy/Metadata/Heaps/GuidHeapTreeNode.cs b/ILSpy/Metadata/Heaps/GuidHeapTreeNode.cs
index f3f742619e..1aaa63c047 100644
--- a/ILSpy/Metadata/Heaps/GuidHeapTreeNode.cs
+++ b/ILSpy/Metadata/Heaps/GuidHeapTreeNode.cs
@@ -16,7 +16,6 @@
 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-using System;
 using System.Collections.Generic;
 using System.Reflection.Metadata;
 using System.Reflection.Metadata.Ecma335;
@@ -30,10 +29,11 @@ internal class GuidHeapTreeNode : MetadataHeapTreeNode
 	{
 		readonly List<GuidHeapEntry> list;
 
-		public GuidHeapTreeNode(PEFile module, MetadataReader metadata)
-			: base(HandleKind.Guid, module, metadata)
+		public GuidHeapTreeNode(MetadataFile metadataFile)
+			: base(HandleKind.Guid, metadataFile)
 		{
 			list = new List<GuidHeapEntry>();
+			var metadata = metadataFile.Metadata;
 			int count = metadata.GetHeapSize(HeapIndex.Guid) >> 4;
 			for (int i = 1; i <= count; i++)
 			{
diff --git a/ILSpy/Metadata/Heaps/StringHeapTreeNode.cs b/ILSpy/Metadata/Heaps/StringHeapTreeNode.cs
index 2e2ca4370a..ea6118ce6c 100644
--- a/ILSpy/Metadata/Heaps/StringHeapTreeNode.cs
+++ b/ILSpy/Metadata/Heaps/StringHeapTreeNode.cs
@@ -16,21 +16,11 @@
 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-using System;
-using System.Collections;
 using System.Collections.Generic;
-using System.Reflection;
 using System.Reflection.Metadata;
 using System.Reflection.Metadata.Ecma335;
-using System.Text;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Data;
 
 using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.DebugInfo;
-using ICSharpCode.Decompiler.Disassembler;
-using ICSharpCode.Decompiler.IL;
 using ICSharpCode.Decompiler.Metadata;
 
 namespace ICSharpCode.ILSpy.Metadata
@@ -39,10 +29,11 @@ internal class StringHeapTreeNode : MetadataHeapTreeNode
 	{
 		readonly List<StringHeapEntry> list;
 
-		public StringHeapTreeNode(PEFile module, MetadataReader metadata)
-			: base(HandleKind.String, module, metadata)
+		public StringHeapTreeNode(MetadataFile metadataFile)
+			: base(HandleKind.String, metadataFile)
 		{
 			list = new List<StringHeapEntry>();
+			var metadata = metadataFile.Metadata;
 			StringHandle handle = MetadataTokens.StringHandle(0);
 			do
 			{
diff --git a/ILSpy/Metadata/Heaps/UserStringHeapTreeNode.cs b/ILSpy/Metadata/Heaps/UserStringHeapTreeNode.cs
index 882a1c3a61..e9ee44a1ec 100644
--- a/ILSpy/Metadata/Heaps/UserStringHeapTreeNode.cs
+++ b/ILSpy/Metadata/Heaps/UserStringHeapTreeNode.cs
@@ -16,21 +16,11 @@
 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-using System;
-using System.Collections;
 using System.Collections.Generic;
-using System.Reflection;
 using System.Reflection.Metadata;
 using System.Reflection.Metadata.Ecma335;
-using System.Text;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Data;
 
 using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.DebugInfo;
-using ICSharpCode.Decompiler.Disassembler;
-using ICSharpCode.Decompiler.IL;
 using ICSharpCode.Decompiler.Metadata;
 
 namespace ICSharpCode.ILSpy.Metadata
@@ -39,11 +29,11 @@ internal class UserStringHeapTreeNode : MetadataHeapTreeNode
 	{
 		readonly List<UserStringHeapEntry> list;
 
-		public UserStringHeapTreeNode(PEFile module, MetadataReader metadata)
-			: base(HandleKind.UserString, module, metadata)
+		public UserStringHeapTreeNode(MetadataFile metadataFile)
+			: base(HandleKind.UserString, metadataFile)
 		{
 			list = new List<UserStringHeapEntry>();
-
+			var metadata = metadataFile.Metadata;
 			UserStringHandle handle = MetadataTokens.UserStringHandle(0);
 			do
 			{
diff --git a/ILSpy/Metadata/MetadataHeapTreeNode.cs b/ILSpy/Metadata/MetadataHeapTreeNode.cs
index 3be811d3df..1e4cc7ea59 100644
--- a/ILSpy/Metadata/MetadataHeapTreeNode.cs
+++ b/ILSpy/Metadata/MetadataHeapTreeNode.cs
@@ -16,33 +16,26 @@
 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-using System;
 using System.Reflection.Metadata;
-using System.Reflection.Metadata.Ecma335;
 using System.Windows.Controls;
 using System.Windows.Threading;
 
 using ICSharpCode.Decompiler.Metadata;
-using ICSharpCode.ILSpy.TextView;
 using ICSharpCode.ILSpy.TreeNodes;
-using ICSharpCode.ILSpy.ViewModels;
-using ICSharpCode.TreeView;
 
 namespace ICSharpCode.ILSpy.Metadata
 {
 	internal abstract class MetadataHeapTreeNode : ILSpyTreeNode
 	{
-		protected PEFile module;
-		protected MetadataReader metadata;
+		protected MetadataFile metadataFile;
 		protected int scrollTarget;
 
 		public HandleKind Kind { get; }
 
-		public MetadataHeapTreeNode(HandleKind kind, PEFile module, MetadataReader metadata)
+		public MetadataHeapTreeNode(HandleKind kind, MetadataFile metadataFile)
 		{
-			this.module = module;
 			this.Kind = kind;
-			this.metadata = metadata;
+			this.metadataFile = metadataFile;
 		}
 
 		internal void ScrollTo(Handle handle)
@@ -53,7 +46,7 @@ internal void ScrollTo(Handle handle)
 		protected void ScrollItemIntoView(DataGrid view, object item)
 		{
 			view.Loaded += View_Loaded;
-			view.Dispatcher.BeginInvoke((Action)(() => view.SelectItem(item)), DispatcherPriority.Background);
+			view.Dispatcher.BeginInvoke(() => view.SelectItem(item), DispatcherPriority.Background);
 		}
 
 		private void View_Loaded(object sender, System.Windows.RoutedEventArgs e)
diff --git a/ILSpy/Metadata/MetadataTableTreeNode.cs b/ILSpy/Metadata/MetadataTableTreeNode.cs
index 204270dc3e..6978e1ec7d 100644
--- a/ILSpy/Metadata/MetadataTableTreeNode.cs
+++ b/ILSpy/Metadata/MetadataTableTreeNode.cs
@@ -23,28 +23,28 @@
 using System.Windows.Threading;
 
 using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.Metadata;
 using ICSharpCode.Decompiler.IL;
+using ICSharpCode.Decompiler.Metadata;
 using ICSharpCode.ILSpy.TreeNodes;
 
 namespace ICSharpCode.ILSpy.Metadata
 {
 	internal abstract class MetadataTableTreeNode : ILSpyTreeNode
 	{
-		protected PEFile module;
+		protected readonly MetadataFile metadataFile;
 		protected int scrollTarget;
 
 		public HandleKind Kind { get; }
 
-		public MetadataTableTreeNode(HandleKind kind, PEFile module)
+		public MetadataTableTreeNode(HandleKind kind, MetadataFile metadataFile)
 		{
-			this.module = module;
 			this.Kind = kind;
+			this.metadataFile = metadataFile;
 		}
 
 		internal void ScrollTo(Handle handle)
 		{
-			this.scrollTarget = module.Metadata.GetRowNumber((EntityHandle)handle);
+			this.scrollTarget = metadataFile.Metadata.GetRowNumber((EntityHandle)handle);
 		}
 
 		protected void ScrollItemIntoView(DataGrid view, object item)
@@ -62,7 +62,7 @@ private void View_Loaded(object sender, System.Windows.RoutedEventArgs e)
 			this.scrollTarget = default;
 		}
 
-		protected static string GenerateTooltip(ref string tooltip, PEFile module, EntityHandle handle)
+		protected static string GenerateTooltip(ref string tooltip, MetadataFile module, EntityHandle handle)
 		{
 			if (tooltip == null)
 			{
@@ -71,7 +71,7 @@ protected static string GenerateTooltip(ref string tooltip, PEFile module, Entit
 					return null;
 				}
 				ITextOutput output = new PlainTextOutput();
-				var context = new MetadataGenericContext(default(TypeDefinitionHandle), module);
+				var context = new MetadataGenericContext(default(TypeDefinitionHandle), module.Metadata);
 				var metadata = module.Metadata;
 				switch (handle.Kind)
 				{
@@ -84,7 +84,7 @@ protected static string GenerateTooltip(ref string tooltip, PEFile module, Entit
 						output.Write(metadata.GetString(moduleReference.Name));
 						break;
 					case HandleKind.AssemblyReference:
-						var asmRef = new Decompiler.Metadata.AssemblyReference(module, (AssemblyReferenceHandle)handle);
+						var asmRef = new Decompiler.Metadata.AssemblyReference(metadata, (AssemblyReferenceHandle)handle);
 						output.Write(asmRef.ToString());
 						break;
 					case HandleKind.Parameter:
@@ -132,12 +132,9 @@ protected static string GenerateTooltip(ref string tooltip, PEFile module, Entit
 
 	internal abstract class DebugMetadataTableTreeNode : MetadataTableTreeNode
 	{
-		protected MetadataReader metadata;
-
-		public DebugMetadataTableTreeNode(HandleKind kind, PEFile module, MetadataReader metadata)
-			: base(kind, module)
+		public DebugMetadataTableTreeNode(HandleKind kind, MetadataFile metadataFile)
+			: base(kind, metadataFile)
 		{
-			this.metadata = metadata;
 		}
 	}
 }
\ No newline at end of file
diff --git a/ILSpy/Metadata/MetadataTablesTreeNode.cs b/ILSpy/Metadata/MetadataTablesTreeNode.cs
index 0a05fcf654..f408d92ede 100644
--- a/ILSpy/Metadata/MetadataTablesTreeNode.cs
+++ b/ILSpy/Metadata/MetadataTablesTreeNode.cs
@@ -16,12 +16,12 @@
 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-using System.Collections.Generic;
+using System;
+using System.Reflection.Metadata;
 using System.Reflection.Metadata.Ecma335;
 
 using ICSharpCode.Decompiler;
 using ICSharpCode.Decompiler.Metadata;
-using ICSharpCode.ILSpy.Options;
 using ICSharpCode.ILSpy.TreeNodes;
 using ICSharpCode.ILSpy.ViewModels;
 
@@ -29,11 +29,11 @@ namespace ICSharpCode.ILSpy.Metadata
 {
 	class MetadataTablesTreeNode : ILSpyTreeNode
 	{
-		private PEFile module;
+		readonly MetadataFile metadataFile;
 
-		public MetadataTablesTreeNode(PEFile module)
+		public MetadataTablesTreeNode(MetadataFile metadataFile)
 		{
-			this.module = module;
+			this.metadataFile = metadataFile;
 			this.LazyLoading = true;
 		}
 
@@ -43,77 +43,169 @@ public MetadataTablesTreeNode(PEFile module)
 
 		protected override void LoadChildren()
 		{
-			if (ShowTable(TableIndex.Module))
-				this.Children.Add(new ModuleTableTreeNode(module));
-			if (ShowTable(TableIndex.TypeRef))
-				this.Children.Add(new TypeRefTableTreeNode(module));
-			if (ShowTable(TableIndex.TypeDef))
-				this.Children.Add(new TypeDefTableTreeNode(module));
-			if (ShowTable(TableIndex.Field))
-				this.Children.Add(new FieldTableTreeNode(module));
-			if (ShowTable(TableIndex.MethodDef))
-				this.Children.Add(new MethodTableTreeNode(module));
-			if (ShowTable(TableIndex.Param))
-				this.Children.Add(new ParamTableTreeNode(module));
-			if (ShowTable(TableIndex.InterfaceImpl))
-				this.Children.Add(new InterfaceImplTableTreeNode(module));
-			if (ShowTable(TableIndex.MemberRef))
-				this.Children.Add(new MemberRefTableTreeNode(module));
-			if (ShowTable(TableIndex.Constant))
-				this.Children.Add(new ConstantTableTreeNode(module));
-			if (ShowTable(TableIndex.CustomAttribute))
-				this.Children.Add(new CustomAttributeTableTreeNode(module));
-			if (ShowTable(TableIndex.FieldMarshal))
-				this.Children.Add(new FieldMarshalTableTreeNode(module));
-			if (ShowTable(TableIndex.DeclSecurity))
-				this.Children.Add(new DeclSecurityTableTreeNode(module));
-			if (ShowTable(TableIndex.ClassLayout))
-				this.Children.Add(new ClassLayoutTableTreeNode(module));
-			if (ShowTable(TableIndex.FieldLayout))
-				this.Children.Add(new FieldLayoutTableTreeNode(module));
-			if (ShowTable(TableIndex.StandAloneSig))
-				this.Children.Add(new StandAloneSigTableTreeNode(module));
-			if (ShowTable(TableIndex.EventMap))
-				this.Children.Add(new EventMapTableTreeNode(module));
-			if (ShowTable(TableIndex.Event))
-				this.Children.Add(new EventTableTreeNode(module));
-			if (ShowTable(TableIndex.PropertyMap))
-				this.Children.Add(new PropertyMapTableTreeNode(module));
-			if (ShowTable(TableIndex.Property))
-				this.Children.Add(new PropertyTableTreeNode(module));
-			if (ShowTable(TableIndex.MethodSemantics))
-				this.Children.Add(new MethodSemanticsTableTreeNode(module));
-			if (ShowTable(TableIndex.MethodImpl))
-				this.Children.Add(new MethodImplTableTreeNode(module));
-			if (ShowTable(TableIndex.ModuleRef))
-				this.Children.Add(new ModuleRefTableTreeNode(module));
-			if (ShowTable(TableIndex.TypeSpec))
-				this.Children.Add(new TypeSpecTableTreeNode(module));
-			if (ShowTable(TableIndex.ImplMap))
-				this.Children.Add(new ImplMapTableTreeNode(module));
-			if (ShowTable(TableIndex.FieldRva))
-				this.Children.Add(new FieldRVATableTreeNode(module));
-			if (ShowTable(TableIndex.Assembly))
-				this.Children.Add(new AssemblyTableTreeNode(module));
-			if (ShowTable(TableIndex.AssemblyRef))
-				this.Children.Add(new AssemblyRefTableTreeNode(module));
-			if (ShowTable(TableIndex.File))
-				this.Children.Add(new FileTableTreeNode(module));
-			if (ShowTable(TableIndex.ExportedType))
-				this.Children.Add(new ExportedTypeTableTreeNode(module));
-			if (ShowTable(TableIndex.ManifestResource))
-				this.Children.Add(new ManifestResourceTableTreeNode(module));
-			if (ShowTable(TableIndex.NestedClass))
-				this.Children.Add(new NestedClassTableTreeNode(module));
-			if (ShowTable(TableIndex.GenericParam))
-				this.Children.Add(new GenericParamTableTreeNode(module));
-			if (ShowTable(TableIndex.MethodSpec))
-				this.Children.Add(new MethodSpecTableTreeNode(module));
-			if (ShowTable(TableIndex.GenericParamConstraint))
-				this.Children.Add(new GenericParamConstraintTableTreeNode(module));
+			if (ShowTable(TableIndex.Module, metadataFile.Metadata))
+				this.Children.Add(new ModuleTableTreeNode(metadataFile));
+			if (ShowTable(TableIndex.TypeRef, metadataFile.Metadata))
+				this.Children.Add(new TypeRefTableTreeNode(metadataFile));
+			if (ShowTable(TableIndex.TypeDef, metadataFile.Metadata))
+				this.Children.Add(new TypeDefTableTreeNode(metadataFile));
+			if (ShowTable(TableIndex.Field, metadataFile.Metadata))
+				this.Children.Add(new FieldTableTreeNode(metadataFile));
+			if (ShowTable(TableIndex.MethodDef, metadataFile.Metadata))
+				this.Children.Add(new MethodTableTreeNode(metadataFile));
+			if (ShowTable(TableIndex.Param, metadataFile.Metadata))
+				this.Children.Add(new ParamTableTreeNode(metadataFile));
+			if (ShowTable(TableIndex.InterfaceImpl, metadataFile.Metadata))
+				this.Children.Add(new InterfaceImplTableTreeNode(metadataFile));
+			if (ShowTable(TableIndex.MemberRef, metadataFile.Metadata))
+				this.Children.Add(new MemberRefTableTreeNode(metadataFile));
+			if (ShowTable(TableIndex.Constant, metadataFile.Metadata))
+				this.Children.Add(new ConstantTableTreeNode(metadataFile));
+			if (ShowTable(TableIndex.CustomAttribute, metadataFile.Metadata))
+				this.Children.Add(new CustomAttributeTableTreeNode(metadataFile));
+			if (ShowTable(TableIndex.FieldMarshal, metadataFile.Metadata))
+				this.Children.Add(new FieldMarshalTableTreeNode(metadataFile));
+			if (ShowTable(TableIndex.DeclSecurity, metadataFile.Metadata))
+				this.Children.Add(new DeclSecurityTableTreeNode(metadataFile));
+			if (ShowTable(TableIndex.ClassLayout, metadataFile.Metadata))
+				this.Children.Add(new ClassLayoutTableTreeNode(metadataFile));
+			if (ShowTable(TableIndex.FieldLayout, metadataFile.Metadata))
+				this.Children.Add(new FieldLayoutTableTreeNode(metadataFile));
+			if (ShowTable(TableIndex.StandAloneSig, metadataFile.Metadata))
+				this.Children.Add(new StandAloneSigTableTreeNode(metadataFile));
+			if (ShowTable(TableIndex.EventMap, metadataFile.Metadata))
+				this.Children.Add(new EventMapTableTreeNode(metadataFile));
+			if (ShowTable(TableIndex.Event, metadataFile.Metadata))
+				this.Children.Add(new EventTableTreeNode(metadataFile));
+			if (ShowTable(TableIndex.PropertyMap, metadataFile.Metadata))
+				this.Children.Add(new PropertyMapTableTreeNode(metadataFile));
+			if (ShowTable(TableIndex.Property, metadataFile.Metadata))
+				this.Children.Add(new PropertyTableTreeNode(metadataFile));
+			if (ShowTable(TableIndex.MethodSemantics, metadataFile.Metadata))
+				this.Children.Add(new MethodSemanticsTableTreeNode(metadataFile));
+			if (ShowTable(TableIndex.MethodImpl, metadataFile.Metadata))
+				this.Children.Add(new MethodImplTableTreeNode(metadataFile));
+			if (ShowTable(TableIndex.ModuleRef, metadataFile.Metadata))
+				this.Children.Add(new ModuleRefTableTreeNode(metadataFile));
+			if (ShowTable(TableIndex.TypeSpec, metadataFile.Metadata))
+				this.Children.Add(new TypeSpecTableTreeNode(metadataFile));
+			if (ShowTable(TableIndex.ImplMap, metadataFile.Metadata))
+				this.Children.Add(new ImplMapTableTreeNode(metadataFile));
+			if (ShowTable(TableIndex.FieldRva, metadataFile.Metadata))
+				this.Children.Add(new FieldRVATableTreeNode(metadataFile));
+			if (ShowTable(TableIndex.Assembly, metadataFile.Metadata))
+				this.Children.Add(new AssemblyTableTreeNode(metadataFile));
+			if (ShowTable(TableIndex.AssemblyRef, metadataFile.Metadata))
+				this.Children.Add(new AssemblyRefTableTreeNode(metadataFile));
+			if (ShowTable(TableIndex.File, metadataFile.Metadata))
+				this.Children.Add(new FileTableTreeNode(metadataFile));
+			if (ShowTable(TableIndex.ExportedType, metadataFile.Metadata))
+				this.Children.Add(new ExportedTypeTableTreeNode(metadataFile));
+			if (ShowTable(TableIndex.ManifestResource, metadataFile.Metadata))
+				this.Children.Add(new ManifestResourceTableTreeNode(metadataFile));
+			if (ShowTable(TableIndex.NestedClass, metadataFile.Metadata))
+				this.Children.Add(new NestedClassTableTreeNode(metadataFile));
+			if (ShowTable(TableIndex.GenericParam, metadataFile.Metadata))
+				this.Children.Add(new GenericParamTableTreeNode(metadataFile));
+			if (ShowTable(TableIndex.MethodSpec, metadataFile.Metadata))
+				this.Children.Add(new MethodSpecTableTreeNode(metadataFile));
+			if (ShowTable(TableIndex.GenericParamConstraint, metadataFile.Metadata))
+				this.Children.Add(new GenericParamConstraintTableTreeNode(metadataFile));
+		}
 
-			bool ShowTable(TableIndex table) => !MainWindow.Instance.CurrentDisplaySettings.HideEmptyMetadataTables || module.Metadata.GetTableRowCount(table) > 0;
+		internal static bool ShowTable(TableIndex table, MetadataReader metadata) => !MainWindow.Instance.CurrentDisplaySettings.HideEmptyMetadataTables || metadata.GetTableRowCount(table) > 0;
 
+		internal static MetadataTableTreeNode CreateTableTreeNode(TableIndex table, MetadataFile metadataFile)
+		{
+			switch (table)
+			{
+				case TableIndex.Module:
+					return new ModuleTableTreeNode(metadataFile);
+				case TableIndex.TypeRef:
+					return new TypeRefTableTreeNode(metadataFile);
+				case TableIndex.TypeDef:
+					return new TypeDefTableTreeNode(metadataFile);
+				case TableIndex.Field:
+					return new FieldTableTreeNode(metadataFile);
+				case TableIndex.MethodDef:
+					return new MethodTableTreeNode(metadataFile);
+				case TableIndex.Param:
+					return new ParamTableTreeNode(metadataFile);
+				case TableIndex.InterfaceImpl:
+					return new InterfaceImplTableTreeNode(metadataFile);
+				case TableIndex.MemberRef:
+					return new MemberRefTableTreeNode(metadataFile);
+				case TableIndex.Constant:
+					return new ConstantTableTreeNode(metadataFile);
+				case TableIndex.CustomAttribute:
+					return new CustomAttributeTableTreeNode(metadataFile);
+				case TableIndex.FieldMarshal:
+					return new FieldMarshalTableTreeNode(metadataFile);
+				case TableIndex.DeclSecurity:
+					return new DeclSecurityTableTreeNode(metadataFile);
+				case TableIndex.ClassLayout:
+					return new ClassLayoutTableTreeNode(metadataFile);
+				case TableIndex.FieldLayout:
+					return new FieldLayoutTableTreeNode(metadataFile);
+				case TableIndex.StandAloneSig:
+					return new StandAloneSigTableTreeNode(metadataFile);
+				case TableIndex.EventMap:
+					return new EventMapTableTreeNode(metadataFile);
+				case TableIndex.Event:
+					return new EventTableTreeNode(metadataFile);
+				case TableIndex.PropertyMap:
+					return new PropertyMapTableTreeNode(metadataFile);
+				case TableIndex.Property:
+					return new PropertyTableTreeNode(metadataFile);
+				case TableIndex.MethodSemantics:
+					return new MethodSemanticsTableTreeNode(metadataFile);
+				case TableIndex.MethodImpl:
+					return new MethodImplTableTreeNode(metadataFile);
+				case TableIndex.ModuleRef:
+					return new ModuleRefTableTreeNode(metadataFile);
+				case TableIndex.TypeSpec:
+					return new TypeSpecTableTreeNode(metadataFile);
+				case TableIndex.ImplMap:
+					return new ImplMapTableTreeNode(metadataFile);
+				case TableIndex.FieldRva:
+					return new FieldRVATableTreeNode(metadataFile);
+				case TableIndex.Assembly:
+					return new AssemblyTableTreeNode(metadataFile);
+				case TableIndex.AssemblyRef:
+					return new AssemblyRefTableTreeNode(metadataFile);
+				case TableIndex.File:
+					return new FileTableTreeNode(metadataFile);
+				case TableIndex.ExportedType:
+					return new ExportedTypeTableTreeNode(metadataFile);
+				case TableIndex.ManifestResource:
+					return new ManifestResourceTableTreeNode(metadataFile);
+				case TableIndex.NestedClass:
+					return new NestedClassTableTreeNode(metadataFile);
+				case TableIndex.GenericParam:
+					return new GenericParamTableTreeNode(metadataFile);
+				case TableIndex.MethodSpec:
+					return new MethodSpecTableTreeNode(metadataFile);
+				case TableIndex.GenericParamConstraint:
+					return new GenericParamConstraintTableTreeNode(metadataFile);
+				case TableIndex.Document:
+					return new DocumentTableTreeNode(metadataFile);
+				case TableIndex.MethodDebugInformation:
+					return new MethodDebugInformationTableTreeNode(metadataFile);
+				case TableIndex.LocalScope:
+					return new LocalScopeTableTreeNode(metadataFile);
+				case TableIndex.LocalVariable:
+					return new LocalVariableTableTreeNode(metadataFile);
+				case TableIndex.LocalConstant:
+					return new LocalConstantTableTreeNode(metadataFile);
+				case TableIndex.ImportScope:
+					return new ImportScopeTableTreeNode(metadataFile);
+				case TableIndex.StateMachineMethod:
+					return new StateMachineMethodTableTreeNode(metadataFile);
+				case TableIndex.CustomDebugInformation:
+					return new CustomDebugInformationTableTreeNode(metadataFile);
+				default:
+					throw new ArgumentException($"Unsupported table index: {table}");
+			}
 		}
 
 		public override bool View(TabPageModel tabPage)
diff --git a/ILSpy/Metadata/MetadataTreeNode.cs b/ILSpy/Metadata/MetadataTreeNode.cs
index 5511d5ad58..59d212c46e 100644
--- a/ILSpy/Metadata/MetadataTreeNode.cs
+++ b/ILSpy/Metadata/MetadataTreeNode.cs
@@ -68,10 +68,10 @@ protected override void LoadChildren()
 			this.Children.Add(new DataDirectoriesTreeNode(module));
 			this.Children.Add(new DebugDirectoryTreeNode(module));
 			this.Children.Add(new MetadataTablesTreeNode(module));
-			this.Children.Add(new StringHeapTreeNode(module, module.Metadata));
-			this.Children.Add(new UserStringHeapTreeNode(module, module.Metadata));
-			this.Children.Add(new GuidHeapTreeNode(module, module.Metadata));
-			this.Children.Add(new BlobHeapTreeNode(module, module.Metadata));
+			this.Children.Add(new StringHeapTreeNode(module));
+			this.Children.Add(new UserStringHeapTreeNode(module));
+			this.Children.Add(new GuidHeapTreeNode(module));
+			this.Children.Add(new BlobHeapTreeNode(module));
 		}
 
 		public MetadataTableTreeNode FindNodeByHandleKind(HandleKind kind)
diff --git a/ILSpy/TextView/AvalonEditTextOutput.cs b/ILSpy/TextView/AvalonEditTextOutput.cs
index dca58e1026..da62890a0f 100644
--- a/ILSpy/TextView/AvalonEditTextOutput.cs
+++ b/ILSpy/TextView/AvalonEditTextOutput.cs
@@ -260,7 +260,7 @@ public void WriteReference(Decompiler.Disassembler.OpCodeInfo opCode, bool omitS
 			references.Add(new ReferenceSegment { StartOffset = start, EndOffset = end, Reference = opCode });
 		}
 
-		public void WriteReference(PEFile module, Handle handle, string text, string protocol = "decompile", bool isDefinition = false)
+		public void WriteReference(MetadataFile metadata, Handle handle, string text, string protocol = "decompile", bool isDefinition = false)
 		{
 			WriteIndent();
 			int start = this.TextLength;
@@ -268,9 +268,9 @@ public void WriteReference(PEFile module, Handle handle, string text, string pro
 			int end = this.TextLength;
 			if (isDefinition)
 			{
-				this.DefinitionLookup.AddDefinition((module, handle), this.TextLength);
+				this.DefinitionLookup.AddDefinition((metadata, handle), this.TextLength);
 			}
-			references.Add(new ReferenceSegment { StartOffset = start, EndOffset = end, Reference = new EntityReference(module, handle, protocol), IsDefinition = isDefinition });
+			references.Add(new ReferenceSegment { StartOffset = start, EndOffset = end, Reference = new EntityReference(metadata, handle, protocol), IsDefinition = isDefinition });
 		}
 
 		public void WriteReference(IType type, string text, bool isDefinition = false)
diff --git a/ILSpy/TextView/DecompilerTextView.cs b/ILSpy/TextView/DecompilerTextView.cs
index c01e7ceb40..a1f2cbc7e9 100644
--- a/ILSpy/TextView/DecompilerTextView.cs
+++ b/ILSpy/TextView/DecompilerTextView.cs
@@ -51,6 +51,7 @@
 using ICSharpCode.Decompiler.CSharp.OutputVisitor;
 using ICSharpCode.Decompiler.CSharp.ProjectDecompiler;
 using ICSharpCode.Decompiler.Documentation;
+using ICSharpCode.Decompiler.Metadata;
 using ICSharpCode.Decompiler.TypeSystem;
 using ICSharpCode.ILSpy.AvalonEdit;
 using ICSharpCode.ILSpy.Options;
@@ -410,7 +411,7 @@ void ToolTipClosed(object? sender, EventArgs e)
 			}
 			else if (segment.Reference is EntityReference unresolvedEntity)
 			{
-				var module = unresolvedEntity.ResolveAssembly(MainWindow.Instance.CurrentAssemblyList);
+				var module = unresolvedEntity.ResolveAssembly(MainWindow.Instance.CurrentAssemblyList) as PEFile;
 				if (module == null)
 					return null;
 				var typeSystem = new DecompilerTypeSystem(module,

From 12cbf14106821348d3d7cbda0b426db2e535253c Mon Sep 17 00:00:00 2001
From: Siegfried Pammer <siegfriedpammer@gmail.com>
Date: Sun, 31 Dec 2023 17:17:41 +0100
Subject: [PATCH 2/5] Clean up node classes.

---
 ICSharpCode.Decompiler/Metadata/PEFile.cs     | 10 +++
 ICSharpCode.ILSpyX/LoadedAssembly.cs          | 47 +++++------
 ILSpy/Metadata/DebugDirectoryTreeNode.cs      |  5 +-
 ILSpy/Metadata/DebugMetadataTablesTreeNode.cs | 77 -------------------
 ILSpy/Metadata/DebugMetadataTreeNode.cs       | 71 -----------------
 ILSpy/Metadata/MetadataTablesTreeNode.cs      | 73 ++----------------
 ILSpy/Metadata/MetadataTreeNode.cs            | 39 +++++-----
 ILSpy/TreeNodes/AssemblyTreeNode.cs           | 13 +++-
 8 files changed, 75 insertions(+), 260 deletions(-)
 delete mode 100644 ILSpy/Metadata/DebugMetadataTablesTreeNode.cs
 delete mode 100644 ILSpy/Metadata/DebugMetadataTreeNode.cs

diff --git a/ICSharpCode.Decompiler/Metadata/PEFile.cs b/ICSharpCode.Decompiler/Metadata/PEFile.cs
index 227053ff9e..8279407671 100644
--- a/ICSharpCode.Decompiler/Metadata/PEFile.cs
+++ b/ICSharpCode.Decompiler/Metadata/PEFile.cs
@@ -34,7 +34,15 @@ namespace ICSharpCode.Decompiler.Metadata
 {
 	public class MetadataFile
 	{
+		public enum MetadataFileKind
+		{
+			PortableExecutable,
+			ProgramDebugDatabase,
+			Metadata
+		}
+
 		public string FileName { get; }
+		public MetadataFileKind Kind { get; }
 		public MetadataReader Metadata { get; }
 
 		public virtual int MetadataOffset { get; }
@@ -46,6 +54,7 @@ public MetadataFile(string fileName, MetadataReaderProvider metadata, MetadataRe
 			this.Metadata = metadata.GetMetadataReader(metadataOptions);
 			this.MetadataOffset = metadataOffset;
 			this.IsEmbedded = isEmbedded;
+			this.Kind = isEmbedded || Path.GetExtension(fileName).Equals(".pdb", StringComparison.OrdinalIgnoreCase) ? MetadataFileKind.ProgramDebugDatabase : MetadataFileKind.Metadata;
 		}
 
 		private protected MetadataFile(string fileName, PEReader reader, MetadataReaderOptions metadataOptions = MetadataReaderOptions.Default)
@@ -55,6 +64,7 @@ private protected MetadataFile(string fileName, PEReader reader, MetadataReaderO
 			if (!reader.HasMetadata)
 				throw new PEFileNotSupportedException("PE file does not contain any managed metadata.");
 			this.Metadata = reader.GetMetadataReader(metadataOptions);
+			this.Kind = MetadataFileKind.PortableExecutable;
 		}
 	}
 
diff --git a/ICSharpCode.ILSpyX/LoadedAssembly.cs b/ICSharpCode.ILSpyX/LoadedAssembly.cs
index feda8088fd..ed9a3fae4e 100644
--- a/ICSharpCode.ILSpyX/LoadedAssembly.cs
+++ b/ICSharpCode.ILSpyX/LoadedAssembly.cs
@@ -268,31 +268,34 @@ public string Text {
 				if (IsLoaded && !HasLoadError)
 				{
 					var result = GetLoadResultAsync().GetAwaiter().GetResult();
-					if (result.PEFile != null)
+					if (result.MetadataFile != null)
 					{
-						var metadata = result.PEFile.Metadata;
-						string? versionOrInfo = null;
-						if (metadata != null)
+						switch (result.MetadataFile.Kind)
 						{
-							if (metadata.IsAssembly)
-							{
-								versionOrInfo = metadata.GetAssemblyDefinition().Version?.ToString();
-								string tfId = GetTargetFrameworkIdAsync().GetAwaiter().GetResult();
-								if (!string.IsNullOrEmpty(tfId))
-									versionOrInfo += ", " + tfId.Replace("Version=", " ");
-							}
-							else
-							{
-								versionOrInfo = ".netmodule";
-							}
+							case MetadataFile.MetadataFileKind.PortableExecutable:
+								var metadata = result.MetadataFile.Metadata;
+								string? versionOrInfo;
+								if (metadata.IsAssembly)
+								{
+									versionOrInfo = metadata.GetAssemblyDefinition().Version?.ToString();
+									string tfId = GetTargetFrameworkIdAsync().GetAwaiter().GetResult();
+									if (!string.IsNullOrEmpty(tfId))
+										versionOrInfo += ", " + tfId.Replace("Version=", " ");
+								}
+								else
+								{
+									versionOrInfo = ".netmodule";
+								}
+								if (versionOrInfo == null)
+									return ShortName;
+								return string.Format("{0} ({1})", ShortName, versionOrInfo);
+							case MetadataFile.MetadataFileKind.ProgramDebugDatabase:
+								return ShortName + " (Debug Metadata)";
+							case MetadataFile.MetadataFileKind.Metadata:
+								return ShortName + " (Metadata)";
+							default:
+								return ShortName;
 						}
-						if (versionOrInfo == null)
-							return ShortName;
-						return string.Format("{0} ({1})", ShortName, versionOrInfo);
-					}
-					else if (result.MetadataFile != null)
-					{
-						return ShortName + " (Metadata)";
 					}
 				}
 				return ShortName;
diff --git a/ILSpy/Metadata/DebugDirectoryTreeNode.cs b/ILSpy/Metadata/DebugDirectoryTreeNode.cs
index 93cfe2592e..0166113e9a 100644
--- a/ILSpy/Metadata/DebugDirectoryTreeNode.cs
+++ b/ILSpy/Metadata/DebugDirectoryTreeNode.cs
@@ -74,8 +74,9 @@ protected override void LoadChildren()
 						break;
 
 					case DebugDirectoryEntryType.EmbeddedPortablePdb:
-						var embeddedPortablePdbReader = module.Reader.ReadEmbeddedPortablePdbDebugDirectoryData(entry).GetMetadataReader();
-						this.Children.Add(new DebugMetadataTreeNode(module));
+						var embeddedPortablePdbProvider = module.Reader.ReadEmbeddedPortablePdbDebugDirectoryData(entry);
+						var embeddedPortablePdbMetadataFile = new MetadataFile(module.FileName, embeddedPortablePdbProvider, isEmbedded: true);
+						this.Children.Add(new MetadataTreeNode(embeddedPortablePdbMetadataFile, "Debug Metadata (Embedded)"));
 						break;
 
 					case DebugDirectoryEntryType.PdbChecksum:
diff --git a/ILSpy/Metadata/DebugMetadataTablesTreeNode.cs b/ILSpy/Metadata/DebugMetadataTablesTreeNode.cs
deleted file mode 100644
index 0580e824f1..0000000000
--- a/ILSpy/Metadata/DebugMetadataTablesTreeNode.cs
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (c) 2021 AlphaSierraPapa for the SharpDevelop Team
-// 
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-// 
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-// 
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System.Reflection.Metadata.Ecma335;
-
-using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.Metadata;
-using ICSharpCode.ILSpy.TreeNodes;
-using ICSharpCode.ILSpy.ViewModels;
-
-namespace ICSharpCode.ILSpy.Metadata
-{
-	class DebugMetadataTablesTreeNode : ILSpyTreeNode
-	{
-		private MetadataFile metadataFile;
-
-		public DebugMetadataTablesTreeNode(MetadataFile metadataFile)
-		{
-			this.metadataFile = metadataFile;
-			this.LazyLoading = true;
-		}
-
-		public override object Text => "Tables";
-
-		public override object Icon => Images.Literal;
-
-		protected override void LoadChildren()
-		{
-			if (ShowTable(TableIndex.Document))
-				this.Children.Add(new DocumentTableTreeNode(metadataFile));
-			if (ShowTable(TableIndex.MethodDebugInformation))
-				this.Children.Add(new MethodDebugInformationTableTreeNode(metadataFile));
-			if (ShowTable(TableIndex.LocalScope))
-				this.Children.Add(new LocalScopeTableTreeNode(metadataFile));
-			if (ShowTable(TableIndex.LocalVariable))
-				this.Children.Add(new LocalVariableTableTreeNode(metadataFile));
-			if (ShowTable(TableIndex.LocalConstant))
-				this.Children.Add(new LocalConstantTableTreeNode(metadataFile));
-			if (ShowTable(TableIndex.ImportScope))
-				this.Children.Add(new ImportScopeTableTreeNode(metadataFile));
-			if (ShowTable(TableIndex.StateMachineMethod))
-				this.Children.Add(new StateMachineMethodTableTreeNode(metadataFile));
-			if (ShowTable(TableIndex.CustomDebugInformation))
-				this.Children.Add(new CustomDebugInformationTableTreeNode(metadataFile));
-
-			bool ShowTable(TableIndex table) => !MainWindow.Instance.CurrentDisplaySettings.HideEmptyMetadataTables || metadataFile.Metadata.GetTableRowCount(table) > 0;
-		}
-
-		public override bool View(TabPageModel tabPage)
-		{
-			tabPage.Title = Text.ToString();
-			tabPage.SupportsLanguageSwitching = false;
-
-			return false;
-		}
-
-		public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
-		{
-			language.WriteCommentLine(output, "Metadata Tables");
-		}
-	}
-}
diff --git a/ILSpy/Metadata/DebugMetadataTreeNode.cs b/ILSpy/Metadata/DebugMetadataTreeNode.cs
deleted file mode 100644
index a6773ffd71..0000000000
--- a/ILSpy/Metadata/DebugMetadataTreeNode.cs
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-// 
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-// 
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-// 
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System.Linq;
-using System.Reflection.Metadata;
-
-using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.Metadata;
-using ICSharpCode.ILSpy.TreeNodes;
-using ICSharpCode.ILSpy.ViewModels;
-
-namespace ICSharpCode.ILSpy.Metadata
-{
-	class DebugMetadataTreeNode : ILSpyTreeNode
-	{
-		private MetadataFile metadataFile;
-
-		public DebugMetadataTreeNode(MetadataFile metadataFile)
-		{
-			this.metadataFile = metadataFile;
-			this.Text = "Debug Metadata (" + (metadataFile.IsEmbedded ? "Embedded" : "From portable PDB") + ")";
-			this.LazyLoading = true;
-		}
-
-		public override object Text { get; }
-
-		public override object Icon => Images.Library;
-
-		public override bool View(TabPageModel tabPage)
-		{
-			tabPage.Title = Text.ToString();
-			tabPage.SupportsLanguageSwitching = false;
-
-			return false;
-		}
-
-		public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
-		{
-			language.WriteCommentLine(output, "Debug Metadata");
-		}
-
-		protected override void LoadChildren()
-		{
-			this.Children.Add(new DebugMetadataTablesTreeNode(metadataFile));
-			this.Children.Add(new StringHeapTreeNode(metadataFile));
-			this.Children.Add(new UserStringHeapTreeNode(metadataFile));
-			this.Children.Add(new GuidHeapTreeNode(metadataFile));
-			this.Children.Add(new BlobHeapTreeNode(metadataFile));
-		}
-
-		public MetadataTableTreeNode FindNodeByHandleKind(HandleKind kind)
-		{
-			return this.Children.OfType<MetadataTableTreeNode>().SingleOrDefault(x => x.Kind == kind);
-		}
-	}
-}
diff --git a/ILSpy/Metadata/MetadataTablesTreeNode.cs b/ILSpy/Metadata/MetadataTablesTreeNode.cs
index f408d92ede..e7b272b461 100644
--- a/ILSpy/Metadata/MetadataTablesTreeNode.cs
+++ b/ILSpy/Metadata/MetadataTablesTreeNode.cs
@@ -43,74 +43,11 @@ public MetadataTablesTreeNode(MetadataFile metadataFile)
 
 		protected override void LoadChildren()
 		{
-			if (ShowTable(TableIndex.Module, metadataFile.Metadata))
-				this.Children.Add(new ModuleTableTreeNode(metadataFile));
-			if (ShowTable(TableIndex.TypeRef, metadataFile.Metadata))
-				this.Children.Add(new TypeRefTableTreeNode(metadataFile));
-			if (ShowTable(TableIndex.TypeDef, metadataFile.Metadata))
-				this.Children.Add(new TypeDefTableTreeNode(metadataFile));
-			if (ShowTable(TableIndex.Field, metadataFile.Metadata))
-				this.Children.Add(new FieldTableTreeNode(metadataFile));
-			if (ShowTable(TableIndex.MethodDef, metadataFile.Metadata))
-				this.Children.Add(new MethodTableTreeNode(metadataFile));
-			if (ShowTable(TableIndex.Param, metadataFile.Metadata))
-				this.Children.Add(new ParamTableTreeNode(metadataFile));
-			if (ShowTable(TableIndex.InterfaceImpl, metadataFile.Metadata))
-				this.Children.Add(new InterfaceImplTableTreeNode(metadataFile));
-			if (ShowTable(TableIndex.MemberRef, metadataFile.Metadata))
-				this.Children.Add(new MemberRefTableTreeNode(metadataFile));
-			if (ShowTable(TableIndex.Constant, metadataFile.Metadata))
-				this.Children.Add(new ConstantTableTreeNode(metadataFile));
-			if (ShowTable(TableIndex.CustomAttribute, metadataFile.Metadata))
-				this.Children.Add(new CustomAttributeTableTreeNode(metadataFile));
-			if (ShowTable(TableIndex.FieldMarshal, metadataFile.Metadata))
-				this.Children.Add(new FieldMarshalTableTreeNode(metadataFile));
-			if (ShowTable(TableIndex.DeclSecurity, metadataFile.Metadata))
-				this.Children.Add(new DeclSecurityTableTreeNode(metadataFile));
-			if (ShowTable(TableIndex.ClassLayout, metadataFile.Metadata))
-				this.Children.Add(new ClassLayoutTableTreeNode(metadataFile));
-			if (ShowTable(TableIndex.FieldLayout, metadataFile.Metadata))
-				this.Children.Add(new FieldLayoutTableTreeNode(metadataFile));
-			if (ShowTable(TableIndex.StandAloneSig, metadataFile.Metadata))
-				this.Children.Add(new StandAloneSigTableTreeNode(metadataFile));
-			if (ShowTable(TableIndex.EventMap, metadataFile.Metadata))
-				this.Children.Add(new EventMapTableTreeNode(metadataFile));
-			if (ShowTable(TableIndex.Event, metadataFile.Metadata))
-				this.Children.Add(new EventTableTreeNode(metadataFile));
-			if (ShowTable(TableIndex.PropertyMap, metadataFile.Metadata))
-				this.Children.Add(new PropertyMapTableTreeNode(metadataFile));
-			if (ShowTable(TableIndex.Property, metadataFile.Metadata))
-				this.Children.Add(new PropertyTableTreeNode(metadataFile));
-			if (ShowTable(TableIndex.MethodSemantics, metadataFile.Metadata))
-				this.Children.Add(new MethodSemanticsTableTreeNode(metadataFile));
-			if (ShowTable(TableIndex.MethodImpl, metadataFile.Metadata))
-				this.Children.Add(new MethodImplTableTreeNode(metadataFile));
-			if (ShowTable(TableIndex.ModuleRef, metadataFile.Metadata))
-				this.Children.Add(new ModuleRefTableTreeNode(metadataFile));
-			if (ShowTable(TableIndex.TypeSpec, metadataFile.Metadata))
-				this.Children.Add(new TypeSpecTableTreeNode(metadataFile));
-			if (ShowTable(TableIndex.ImplMap, metadataFile.Metadata))
-				this.Children.Add(new ImplMapTableTreeNode(metadataFile));
-			if (ShowTable(TableIndex.FieldRva, metadataFile.Metadata))
-				this.Children.Add(new FieldRVATableTreeNode(metadataFile));
-			if (ShowTable(TableIndex.Assembly, metadataFile.Metadata))
-				this.Children.Add(new AssemblyTableTreeNode(metadataFile));
-			if (ShowTable(TableIndex.AssemblyRef, metadataFile.Metadata))
-				this.Children.Add(new AssemblyRefTableTreeNode(metadataFile));
-			if (ShowTable(TableIndex.File, metadataFile.Metadata))
-				this.Children.Add(new FileTableTreeNode(metadataFile));
-			if (ShowTable(TableIndex.ExportedType, metadataFile.Metadata))
-				this.Children.Add(new ExportedTypeTableTreeNode(metadataFile));
-			if (ShowTable(TableIndex.ManifestResource, metadataFile.Metadata))
-				this.Children.Add(new ManifestResourceTableTreeNode(metadataFile));
-			if (ShowTable(TableIndex.NestedClass, metadataFile.Metadata))
-				this.Children.Add(new NestedClassTableTreeNode(metadataFile));
-			if (ShowTable(TableIndex.GenericParam, metadataFile.Metadata))
-				this.Children.Add(new GenericParamTableTreeNode(metadataFile));
-			if (ShowTable(TableIndex.MethodSpec, metadataFile.Metadata))
-				this.Children.Add(new MethodSpecTableTreeNode(metadataFile));
-			if (ShowTable(TableIndex.GenericParamConstraint, metadataFile.Metadata))
-				this.Children.Add(new GenericParamConstraintTableTreeNode(metadataFile));
+			foreach (var table in Enum.GetValues<TableIndex>())
+			{
+				if (ShowTable(table, metadataFile.Metadata))
+					this.Children.Add(CreateTableTreeNode(table, metadataFile));
+			}
 		}
 
 		internal static bool ShowTable(TableIndex table, MetadataReader metadata) => !MainWindow.Instance.CurrentDisplaySettings.HideEmptyMetadataTables || metadata.GetTableRowCount(table) > 0;
diff --git a/ILSpy/Metadata/MetadataTreeNode.cs b/ILSpy/Metadata/MetadataTreeNode.cs
index 59d212c46e..7bcbec8107 100644
--- a/ILSpy/Metadata/MetadataTreeNode.cs
+++ b/ILSpy/Metadata/MetadataTreeNode.cs
@@ -21,11 +21,11 @@
 using System.Globalization;
 using System.Linq;
 using System.Reflection.Metadata;
+using System.Reflection.Metadata.Ecma335;
 using System.Windows.Data;
 
 using ICSharpCode.Decompiler;
 using ICSharpCode.Decompiler.Metadata;
-using ICSharpCode.ILSpy.Properties;
 using ICSharpCode.ILSpy.TreeNodes;
 using ICSharpCode.ILSpy.ViewModels;
 
@@ -33,17 +33,17 @@ namespace ICSharpCode.ILSpy.Metadata
 {
 	class MetadataTreeNode : ILSpyTreeNode
 	{
-		private readonly PEFile module;
-		private AssemblyTreeNode assemblyTreeNode;
+		private readonly MetadataFile metadataFile;
+		private readonly string title;
 
-		public MetadataTreeNode(PEFile module, AssemblyTreeNode assemblyTreeNode)
+		public MetadataTreeNode(MetadataFile module, string title)
 		{
-			this.module = module;
-			this.assemblyTreeNode = assemblyTreeNode;
+			this.metadataFile = module;
+			this.title = title;
 			this.LazyLoading = true;
 		}
 
-		public override object Text => Resources.Metadata;
+		public override object Text => title;
 
 		public override object Icon => Images.Library;
 
@@ -57,21 +57,24 @@ public override bool View(TabPageModel tabPage)
 
 		public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
 		{
-			language.WriteCommentLine(output, "Metadata");
+			language.WriteCommentLine(output, title);
 		}
 
 		protected override void LoadChildren()
 		{
-			this.Children.Add(new DosHeaderTreeNode(module));
-			this.Children.Add(new CoffHeaderTreeNode(module));
-			this.Children.Add(new OptionalHeaderTreeNode(module));
-			this.Children.Add(new DataDirectoriesTreeNode(module));
-			this.Children.Add(new DebugDirectoryTreeNode(module));
-			this.Children.Add(new MetadataTablesTreeNode(module));
-			this.Children.Add(new StringHeapTreeNode(module));
-			this.Children.Add(new UserStringHeapTreeNode(module));
-			this.Children.Add(new GuidHeapTreeNode(module));
-			this.Children.Add(new BlobHeapTreeNode(module));
+			if (metadataFile is PEFile module)
+			{
+				this.Children.Add(new DosHeaderTreeNode(module));
+				this.Children.Add(new CoffHeaderTreeNode(module));
+				this.Children.Add(new OptionalHeaderTreeNode(module));
+				this.Children.Add(new DataDirectoriesTreeNode(module));
+				this.Children.Add(new DebugDirectoryTreeNode(module));
+			}
+			this.Children.Add(new MetadataTablesTreeNode(metadataFile));
+			this.Children.Add(new StringHeapTreeNode(metadataFile));
+			this.Children.Add(new UserStringHeapTreeNode(metadataFile));
+			this.Children.Add(new GuidHeapTreeNode(metadataFile));
+			this.Children.Add(new BlobHeapTreeNode(metadataFile));
 		}
 
 		public MetadataTableTreeNode FindNodeByHandleKind(HandleKind kind)
diff --git a/ILSpy/TreeNodes/AssemblyTreeNode.cs b/ILSpy/TreeNodes/AssemblyTreeNode.cs
index 2cc3744232..7f32ea8951 100644
--- a/ILSpy/TreeNodes/AssemblyTreeNode.cs
+++ b/ILSpy/TreeNodes/AssemblyTreeNode.cs
@@ -194,6 +194,15 @@ protected override void LoadChildren()
 					var package = loadResult.Package;
 					this.Children.AddRange(PackageFolderTreeNode.LoadChildrenForFolder(package.RootFolder));
 				}
+				else if (loadResult.MetadataFile != null)
+				{
+					var metadata = loadResult.MetadataFile;
+					this.Children.Add(new MetadataTablesTreeNode(metadata));
+					this.Children.Add(new StringHeapTreeNode(metadata));
+					this.Children.Add(new UserStringHeapTreeNode(metadata));
+					this.Children.Add(new GuidHeapTreeNode(metadata));
+					this.Children.Add(new BlobHeapTreeNode(metadata));
+				}
 			}
 			catch (Exception ex)
 			{
@@ -205,12 +214,12 @@ void LoadChildrenForPEFile(PEFile module)
 		{
 			typeSystem = LoadedAssembly.GetTypeSystemOrNull();
 			var assembly = (MetadataModule)typeSystem.MainModule;
-			this.Children.Add(new Metadata.MetadataTreeNode(module, this));
+			this.Children.Add(new MetadataTreeNode(module, Resources.Metadata));
 			Decompiler.DebugInfo.IDebugInfoProvider debugInfo = LoadedAssembly.GetDebugInfoOrNull();
 			if (debugInfo is PortableDebugInfoProvider ppdb
 				&& ppdb.GetMetadataReader() is System.Reflection.Metadata.MetadataReader reader)
 			{
-				this.Children.Add(new Metadata.DebugMetadataTreeNode(module, ppdb.IsEmbedded, reader));
+				this.Children.Add(new MetadataTreeNode(ppdb.ToMetadataFile(), $"Debug Metadata ({(ppdb.IsEmbedded ? "Embedded" : "From portable PDB")})"));
 			}
 			this.Children.Add(new ReferenceFolderTreeNode(module, this));
 			if (module.Resources.Any())

From 5dd4c2c6822d0eb762495c415f5706e530fd08b2 Mon Sep 17 00:00:00 2001
From: Siegfried Pammer <siegfriedpammer@gmail.com>
Date: Sun, 31 Dec 2023 17:18:21 +0100
Subject: [PATCH 3/5] Add DumpMetadataInfo in MetadataTreeNode

---
 ILSpy/Metadata/MetadataTreeNode.cs | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/ILSpy/Metadata/MetadataTreeNode.cs b/ILSpy/Metadata/MetadataTreeNode.cs
index 7bcbec8107..cbbd6d0a70 100644
--- a/ILSpy/Metadata/MetadataTreeNode.cs
+++ b/ILSpy/Metadata/MetadataTreeNode.cs
@@ -58,6 +58,34 @@ public override bool View(TabPageModel tabPage)
 		public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
 		{
 			language.WriteCommentLine(output, title);
+
+			DumpMetadataInfo(language, output, this.metadataFile.Metadata);
+		}
+
+		internal static void DumpMetadataInfo(Language language, ITextOutput output, MetadataReader metadata)
+		{
+			language.WriteCommentLine(output, "MetadataKind: " + metadata.MetadataKind);
+			language.WriteCommentLine(output, "MetadataVersion: " + metadata.MetadataVersion);
+
+			if (metadata.DebugMetadataHeader is { } header)
+			{
+				output.WriteLine();
+				language.WriteCommentLine(output, "Header:");
+				language.WriteCommentLine(output, "Id: " + header.Id.ToHexString(header.Id.Length));
+				language.WriteCommentLine(output, "EntryPoint: " + MetadataTokens.GetToken(header.EntryPoint).ToString("X8"));
+			}
+
+			output.WriteLine();
+			language.WriteCommentLine(output, "Tables:");
+
+			foreach (var table in Enum.GetValues<TableIndex>())
+			{
+				int count = metadata.GetTableRowCount(table);
+				if (count > 0)
+				{
+					language.WriteCommentLine(output, $"{(byte)table:X2} {table}: {count} rows");
+				}
+			}
 		}
 
 		protected override void LoadChildren()

From 9c577ba1566617f8b78f6f85a1651a789b66e993 Mon Sep 17 00:00:00 2001
From: Siegfried Pammer <siegfriedpammer@gmail.com>
Date: Sun, 31 Dec 2023 17:13:45 +0100
Subject: [PATCH 4/5] Update icons

---
 ILSpy/Images/Header.svg                       |  1 +
 ILSpy/Images/Header.xaml                      | 11 +++
 ILSpy/Images/Heap.svg                         |  1 +
 ILSpy/Images/Heap.xaml                        | 10 +++
 ILSpy/Images/Images.cs                        | 10 +++
 ILSpy/Images/ListFolder.Open.svg              |  1 +
 ILSpy/Images/ListFolder.Open.xaml             | 12 +++
 ILSpy/Images/ListFolder.svg                   |  1 +
 ILSpy/Images/ListFolder.xaml                  | 11 +++
 ILSpy/Images/Metadata.svg                     |  1 +
 ILSpy/Images/Metadata.xaml                    | 15 ++++
 ILSpy/Images/MetadataFile.svg                 | 73 ++++++++++++++++++
 ILSpy/Images/MetadataFile.xaml                | 29 +++++++
 ILSpy/Images/MetadataTable.svg                |  1 +
 ILSpy/Images/MetadataTable.xaml               | 10 +++
 ILSpy/Images/MetadataTableGroup.svg           |  1 +
 ILSpy/Images/MetadataTableGroup.xaml          | 10 +++
 ILSpy/Images/ProgramDebugDatabase.svg         |  1 +
 ILSpy/Images/ProgramDebugDatabase.xaml        | 14 ++++
 ILSpy/Images/README.md                        | 11 ++-
 ILSpy/Metadata/CoffHeaderTreeNode.cs          |  2 +-
 .../CorTables/AssemblyRefTableTreeNode.cs     |  2 -
 .../CorTables/AssemblyTableTreeNode.cs        |  2 -
 .../CorTables/ClassLayoutTableTreeNode.cs     |  2 -
 .../CorTables/ConstantTableTreeNode.cs        |  2 -
 .../CorTables/CustomAttributeTableTreeNode.cs |  2 -
 .../CorTables/DeclSecurityTableTreeNode.cs    |  2 -
 .../CorTables/EventMapTableTreeNode.cs        |  2 -
 .../Metadata/CorTables/EventTableTreeNode.cs  |  2 -
 .../CorTables/ExportedTypeTableTreeNode.cs    |  2 -
 .../CorTables/FieldLayoutTableTreeNode.cs     |  2 -
 .../CorTables/FieldMarshalTableTreeNode.cs    |  2 -
 .../Metadata/CorTables/FieldTableTreeNode.cs  |  2 -
 ILSpy/Metadata/CorTables/FileTableTreeNode.cs |  2 -
 .../GenericParamConstraintTableTreeNode.cs    |  2 -
 .../CorTables/GenericParamTableTreeNode.cs    |  2 -
 .../CorTables/ImplMapTableTreeNode.cs         |  2 -
 .../CorTables/InterfaceImplTableTreeNode.cs   |  2 -
 .../ManifestResourceTableTreeNode.cs          |  2 -
 .../CorTables/MemberRefTableTreeNode.cs       |  2 -
 .../CorTables/MethodImplTableTreeNode.cs      |  2 -
 .../CorTables/MethodSemanticsTableTreeNode.cs |  2 -
 .../CorTables/MethodSpecTableTreeNode.cs      |  2 -
 .../Metadata/CorTables/MethodTableTreeNode.cs |  2 -
 .../CorTables/ModuleRefTableTreeNode.cs       |  2 -
 .../Metadata/CorTables/ModuleTableTreeNode.cs |  2 -
 .../CorTables/NestedClassTableTreeNode.cs     |  2 -
 .../Metadata/CorTables/ParamTableTreeNode.cs  |  2 -
 .../CorTables/PropertyMapTableTreeNode.cs     |  2 -
 .../CorTables/PropertyTableTreeNode.cs        |  2 -
 .../CorTables/StandAloneSigTableTreeNode.cs   |  2 -
 .../CorTables/TypeDefTableTreeNode.cs         |  2 -
 .../CorTables/TypeRefTableTreeNode.cs         |  2 -
 .../CorTables/TypeSpecTableTreeNode.cs        |  2 -
 ILSpy/Metadata/DataDirectoriesTreeNode.cs     |  6 +-
 .../DebugDirectory/CodeViewTreeNode.cs        |  3 +-
 .../DebugDirectoryEntryTreeNode.cs            |  5 +-
 .../DebugDirectory/PdbChecksumTreeNode.cs     |  2 +-
 ILSpy/Metadata/DebugDirectoryTreeNode.cs      |  4 +-
 ILSpy/Metadata/DebugMetadataTablesTreeNode.cs | 77 +++++++++++++++++++
 .../CustomDebugInformationTableTreeNode.cs    |  2 -
 .../DebugTables/DocumentTableTreeNode.cs      |  2 -
 .../DebugTables/ImportScopeTableTreeNode.cs   |  2 -
 .../DebugTables/LocalConstantTableTreeNode.cs |  2 -
 .../DebugTables/LocalScopeTableTreeNode.cs    |  2 -
 .../DebugTables/LocalVariableTableTreeNode.cs |  2 -
 .../MethodDebugInformationTableTreeNode.cs    |  2 -
 .../StateMachineMethodTableTreeNode.cs        |  2 -
 ILSpy/Metadata/DosHeaderTreeNode.cs           |  4 +-
 ILSpy/Metadata/Heaps/BlobHeapTreeNode.cs      |  3 -
 ILSpy/Metadata/Heaps/GuidHeapTreeNode.cs      |  2 -
 ILSpy/Metadata/Heaps/StringHeapTreeNode.cs    |  2 -
 .../Metadata/Heaps/UserStringHeapTreeNode.cs  |  2 -
 ILSpy/Metadata/MetadataHeapTreeNode.cs        |  7 +-
 ILSpy/Metadata/MetadataTableTreeNode.cs       |  2 +
 ILSpy/Metadata/MetadataTablesTreeNode.cs      |  2 +-
 ILSpy/Metadata/MetadataTreeNode.cs            |  2 +-
 ILSpy/Metadata/OptionalHeaderTreeNode.cs      |  2 +-
 ILSpy/TreeNodes/AssemblyTreeNode.cs           | 19 ++++-
 79 files changed, 335 insertions(+), 117 deletions(-)
 create mode 100644 ILSpy/Images/Header.svg
 create mode 100644 ILSpy/Images/Header.xaml
 create mode 100644 ILSpy/Images/Heap.svg
 create mode 100644 ILSpy/Images/Heap.xaml
 create mode 100644 ILSpy/Images/ListFolder.Open.svg
 create mode 100644 ILSpy/Images/ListFolder.Open.xaml
 create mode 100644 ILSpy/Images/ListFolder.svg
 create mode 100644 ILSpy/Images/ListFolder.xaml
 create mode 100644 ILSpy/Images/Metadata.svg
 create mode 100644 ILSpy/Images/Metadata.xaml
 create mode 100644 ILSpy/Images/MetadataFile.svg
 create mode 100644 ILSpy/Images/MetadataFile.xaml
 create mode 100644 ILSpy/Images/MetadataTable.svg
 create mode 100644 ILSpy/Images/MetadataTable.xaml
 create mode 100644 ILSpy/Images/MetadataTableGroup.svg
 create mode 100644 ILSpy/Images/MetadataTableGroup.xaml
 create mode 100644 ILSpy/Images/ProgramDebugDatabase.svg
 create mode 100644 ILSpy/Images/ProgramDebugDatabase.xaml
 create mode 100644 ILSpy/Metadata/DebugMetadataTablesTreeNode.cs

diff --git a/ILSpy/Images/Header.svg b/ILSpy/Images/Header.svg
new file mode 100644
index 0000000000..44056d1b88
--- /dev/null
+++ b/ILSpy/Images/Header.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-bg{fill:#424242}.icon-vs-fg{fill:#f0eff1}.icon-vs-blue{fill:#1ba1e2}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M15 0v16H1V0h14z" id="outline"/><path class="icon-vs-bg" d="M2 1v14h12V1H2zm11 13H3V2h10v12zm-1-1H4v-1h8v1zm0-2H4v-1h8v1zm0-2H4V8h8v1z" id="iconBg"/><path class="icon-vs-fg" d="M11 5H5V4h6v1zm2-3v12H3V2h10zm-1 10H4v1h8v-1zm0-2H4v1h8v-1zm0-2H4v1h8V8zm0-5H4v3h8V3z" id="iconFg"/><path class="icon-vs-blue" d="M12 3H4v3h8V3zm-1 2H5V4h6v1z" id="colorImportance"/></svg>
\ No newline at end of file
diff --git a/ILSpy/Images/Header.xaml b/ILSpy/Images/Header.xaml
new file mode 100644
index 0000000000..ea115bdd72
--- /dev/null
+++ b/ILSpy/Images/Header.xaml
@@ -0,0 +1,11 @@
+<!-- This file was generated by the AiToXaml tool.-->
+<!-- Tool Version: 14.0.22307.0 -->
+<DrawingGroup xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
+  <DrawingGroup.Children>
+    <GeometryDrawing Brush="#00FFFFFF" Geometry="F1M16,16L0,16 0,0 16,0z" />
+    <GeometryDrawing Brush="#FFF6F6F6" Geometry="F1M1,16L15,16 15,0 1,0z" />
+    <GeometryDrawing Brush="#FF424242" Geometry="F1M12,9L4,9 4,8 12,8z M12,11L4,11 4,10 12,10z M12,13L4,13 4,12 12,12z M13,14L3,14 3,2 13,2z M2,15L14,15 14,1 2,1z" />
+    <GeometryDrawing Brush="#FFF0EFF1" Geometry="F1M12,3L4,3 4,6 12,6z M12,8L4,8 4,9 12,9z M12,10L4,10 4,11 12,11z M12,12L4,12 4,13 12,13z M13,14L3,14 3,2 13,2z M11,5L5,5 5,4 11,4z" />
+    <GeometryDrawing Brush="#FF1BA1E2" Geometry="F1M11,5L5,5 5,4 11,4z M12,3L4,3 4,6 12,6z" />
+  </DrawingGroup.Children>
+</DrawingGroup>
\ No newline at end of file
diff --git a/ILSpy/Images/Heap.svg b/ILSpy/Images/Heap.svg
new file mode 100644
index 0000000000..72f0dc2650
--- /dev/null
+++ b/ILSpy/Images/Heap.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-bg{fill:#424242}.icon-vs-fg{fill:#f0eff1}</style><path class="icon-canvas-transparent" d="M15.993 16h-16V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M16 15H1V1h15v14z" id="outline"/><path class="icon-vs-fg" d="M14 13H3v-2h11v2zm0-3H3V8h11v2zm0-3H3V5h11v2z" id="iconFg"/><g id="iconBg"><path class="icon-vs-bg" d="M2 2v12h13V2H2zm12 11H3v-2h11v2zm0-3H3V8h11v2zm0-3H3V5h11v2z"/></g></svg>
\ No newline at end of file
diff --git a/ILSpy/Images/Heap.xaml b/ILSpy/Images/Heap.xaml
new file mode 100644
index 0000000000..2e96c9a8f9
--- /dev/null
+++ b/ILSpy/Images/Heap.xaml
@@ -0,0 +1,10 @@
+<!-- This file was generated by the AiToXaml tool.-->
+<!-- Tool Version: 14.0.22307.0 -->
+<DrawingGroup xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
+  <DrawingGroup.Children>
+    <GeometryDrawing Brush="#00FFFFFF" Geometry="F1M15.993,16L-0.00699999999999967,16 -0.00699999999999967,0 15.993,0z" />
+    <GeometryDrawing Brush="#FFF6F6F6" Geometry="F1M1,15L16,15 16,1 1,1z" />
+    <GeometryDrawing Brush="#FFEFEFF0" Geometry="F1M14,7L3,7 3,5 14,5z M14,10L3,10 3,8 14,8z M14,13L3,13 3,11 14,11z" />
+    <GeometryDrawing Brush="#FF424242" Geometry="F1M14,7L3,7 3,5 14,5z M14,10L3,10 3,8 14,8z M14,13L3,13 3,11 14,11z M2,14L15,14 15,2 2,2z" />
+  </DrawingGroup.Children>
+</DrawingGroup>
\ No newline at end of file
diff --git a/ILSpy/Images/Images.cs b/ILSpy/Images/Images.cs
index 3222281bae..ab1012278f 100644
--- a/ILSpy/Images/Images.cs
+++ b/ILSpy/Images/Images.cs
@@ -56,6 +56,16 @@ static ImageSource Load(string icon)
 
 		public static readonly ImageSource ReferenceFolder = Load("ReferenceFolder");
 		public static readonly ImageSource NuGet = Load(null, "Images/NuGet.png");
+		public static readonly ImageSource MetadataFile = Load("MetadataFile");
+		public static readonly ImageSource ProgramDebugDatabase = Load("ProgramDebugDatabase");
+
+		public static readonly ImageSource Metadata = Load("Metadata");
+		public static readonly ImageSource Heap = Load("Heap");
+		public static readonly ImageSource Header = Load("Header");
+		public static readonly ImageSource MetadataTable = Load("MetadataTable");
+		public static readonly ImageSource MetadataTableGroup = Load("MetadataTableGroup");
+		public static readonly ImageSource ListFolder = Load("ListFolder");
+		public static readonly ImageSource ListFolderOpen = Load("ListFolder.Open");
 
 		public static readonly ImageSource SubTypes = Load("SubTypes");
 		public static readonly ImageSource SuperTypes = Load("SuperTypes");
diff --git a/ILSpy/Images/ListFolder.Open.svg b/ILSpy/Images/ListFolder.Open.svg
new file mode 100644
index 0000000000..b7b5c2bdce
--- /dev/null
+++ b/ILSpy/Images/ListFolder.Open.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-fg{fill:#f0eff1}.icon-folder{fill:#dcb67a}.icon-vs-bg{fill:#424242}</style><path class="icon-canvas-transparent" d="M0 0h16v16H0V0z" id="canvas"/><path class="icon-vs-out" d="M16 6.969V16H5v-2.031H2s-.86-.022-1.43-.566c-.343-.332-.57-.817-.57-1.434v-9c0-1.303 1.005-2 2-2h7.116l1 2H13c.97 0 2 .701 2 2v2h1z" id="outline"/><path class="icon-vs-fg" d="M7 9h1v1H7V9zm0 3h1v-1H7v1zm0 2h1v-1H7v1zm2 0h5v-1H9v1zm0-2h5v-1H9v1zm0-3v1h5V9H9z" id="iconFg"/><g id="iconBg"><path class="icon-folder" d="M2 3h6l1 2h4v2h1V5c0-1-1.236-1-1-1H9.5l-1-2H2S1 2 1 3v9c0 .97.94.984.997.984H2V3z"/><path class="icon-folder" d="M5 8H4l-2 5h3z"/><path class="icon-vs-bg" d="M6 8v7h9V8H6zm1 1h1v1H7V9zm0 2h1v1H7v-1zm0 3v-1h1v1H7zm7 0H9v-1h5v1zm0-2H9v-1h5v1zm0-2H9V9h5v1z"/></g></svg>
\ No newline at end of file
diff --git a/ILSpy/Images/ListFolder.Open.xaml b/ILSpy/Images/ListFolder.Open.xaml
new file mode 100644
index 0000000000..e760832358
--- /dev/null
+++ b/ILSpy/Images/ListFolder.Open.xaml
@@ -0,0 +1,12 @@
+<!-- This file was generated by the AiToXaml tool.-->
+<!-- Tool Version: 14.0.22307.0 -->
+<DrawingGroup xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
+  <DrawingGroup.Children>
+    <GeometryDrawing Brush="#00FFFFFF" Geometry="F1M0,0L16,0 16,16 0,16z" />
+    <GeometryDrawing Brush="#FFF6F6F6" Geometry="F1M16,6.9688L16,6.9998 16,8.1648 16,15.9998 5,15.9998 5,13.9688 2,13.9688C2,13.9688 1.14,13.9478 0.57,13.4038 0.227,13.0718 0,12.5858 0,11.9688L0,2.9688C0,1.6658,1.005,0.9688,2,0.9688L9.116,0.9688 10.116,2.9688 13,2.9688C13.97,2.9688,15,3.6698,15,4.9688L15,6.9688z" />
+    <GeometryDrawing Brush="#FFF0EFF1" Geometry="F1M9,10L14,10 14,9 9,9z M9,12L14,12 14,11 9,11z M9,14L14,14 14,13 9,13z M7,14L8,14 8,13 7,13z M7,12L8,12 8,11 7,11z M7,9L8,9 8,10 7,10z" />
+    <GeometryDrawing Brush="#FFDCB67A" Geometry="F1M2,3L8,3 9,5 13,5 13,7 14,7 14,5C14,4,12.764,4,13,4L9.5,4 8.5,2 2,2C2,2,1,2,1,3L1,12C1,12.97,1.94,12.984,1.997,12.984L2,12.984z" />
+    <GeometryDrawing Brush="#FFDCB67A" Geometry="F1M5,8L4,8 2,13 5,13z" />
+    <GeometryDrawing Brush="#FF424242" Geometry="F1M14,10L9,10 9,9 14,9z M14,12L9,12 9,11 14,11z M14,14L9,14 9,13 14,13z M7,13L8,13 8,14 7,14z M7,11L8,11 8,12 7,12z M7,9L8,9 8,10 7,10z M6,15L15,15 15,8 6,8z" />
+  </DrawingGroup.Children>
+</DrawingGroup>
\ No newline at end of file
diff --git a/ILSpy/Images/ListFolder.svg b/ILSpy/Images/ListFolder.svg
new file mode 100644
index 0000000000..b9c47a7ddc
--- /dev/null
+++ b/ILSpy/Images/ListFolder.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16"><style type="text/css">.icon-canvas-transparent{opacity:0;fill:#F6F6F6;} .icon-vs-out{fill:#F6F6F6;} .icon-folder{fill:#DCB67A;} .icon-vs-fg{fill:#F0EFF1;} .icon-vs-bg{fill:#424242;}</style><path class="icon-canvas-transparent" d="M0 0h16v16h-16v-16z" id="canvas"/><path class="icon-vs-out" d="M14.996 4.5v8c0 .827-.673 1.5-1.5 1.5h-2.496v2h-11v-13.5c0-.827.673-1.5 1.5-1.5h8.11l1 2h2.886c.827 0 1.5.673 1.5 1.5z" id="outline"/><g id="iconBg"><path class="icon-folder" d="M13.496 4h-3.504l-1-2h-7.492c-.275 0-.5.224-.5.5v4.5h10v6h2.496c.277 0 .5-.224.5-.5v-8c0-.276-.223-.5-.5-.5zm-11.496 0v-1h6.374l.5 1h-6.874z"/><path class="icon-vs-bg" d="M1 8v7h9v-7h-9zm1 1h1v1h-1v-1zm0 2h1v1h-1v-1zm0 3v-1h1v1h-1zm7 0h-5v-1h5v1zm0-2h-5v-1h5v1zm0-2h-5v-1h5v1z"/></g><path class="icon-vs-fg" d="M2 9h1v1h-1v-1zm0 2h1v1h-1v-1zm0 3v-1h1v1h-1zm7 0h-5v-1h5v1zm0-2h-5v-1h5v1zm0-2h-5v-1h5v1zm-7-7h6.374l.5 1h-6.874v-1z" id="iconFg"/></svg>
\ No newline at end of file
diff --git a/ILSpy/Images/ListFolder.xaml b/ILSpy/Images/ListFolder.xaml
new file mode 100644
index 0000000000..a154bef400
--- /dev/null
+++ b/ILSpy/Images/ListFolder.xaml
@@ -0,0 +1,11 @@
+<!-- This file was generated by the AiToXaml tool.-->
+<!-- Tool Version: 14.0.22307.0 -->
+<DrawingGroup xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
+  <DrawingGroup.Children>
+    <GeometryDrawing Brush="#00FFFFFF" Geometry="F1M0,0L16,0 16,16 0,16z" />
+    <GeometryDrawing Brush="#FFF6F6F6" Geometry="F1M14.9961,4.5L14.9961,12.5C14.9961,13.327,14.3231,14,13.4961,14L11.0001,14 11.0001,16 9.99999999997669E-05,16 9.99999999997669E-05,12.5 9.99999999997669E-05,7 9.99999999997669E-05,2.5C9.99999999997669E-05,1.673,0.6731,1,1.5001,1L9.6101,1 10.6101,3 13.4961,3C14.3231,3,14.9961,3.673,14.9961,4.5" />
+    <GeometryDrawing Brush="#FFDCB67A" Geometry="F1M2,4L2,3 8.374,3 8.874,4z M13.496,4L10,4 9.992,4 8.992,2 1.5,2C1.225,2,1,2.224,1,2.5L1,7 11,7 11,13 13.496,13C13.773,13,13.996,12.776,13.996,12.5L13.996,4.5C13.996,4.224,13.773,4,13.496,4" />
+    <GeometryDrawing Brush="#FF424242" Geometry="F1M9,10L4,10 4,9 9,9z M9,12L4,12 4,11 9,11z M9,14L4,14 4,13 9,13z M2,13L3,13 3,14 2,14z M2,11L3,11 3,12 2,12z M2,9L3,9 3,10 2,10z M1,15L10,15 10,8 1,8z" />
+    <GeometryDrawing Brush="#FFEFEFF0" Geometry="F1M2,3L8.374,3 8.874,4 2,4z M9,10L4,10 4,9 9,9z M9,12L4,12 4,11 9,11z M9,14L4,14 4,13 9,13z M2,13L3,13 3,14 2,14z M2,11L3,11 3,12 2,12z M2,9L3,9 3,10 2,10z" />
+  </DrawingGroup.Children>
+</DrawingGroup>
\ No newline at end of file
diff --git a/ILSpy/Images/Metadata.svg b/ILSpy/Images/Metadata.svg
new file mode 100644
index 0000000000..eb8ff38659
--- /dev/null
+++ b/ILSpy/Images/Metadata.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.st0{opacity:0}.st0,.st1{fill:#f6f6f6}.st2{fill:#424242}.st3{fill:#f0eff1}</style><g id="outline"><path class="st0" d="M0 0h16v16H0z"/><path class="st1" d="M15 4.465v7.07L8.303 16h-.606L1 11.535v-7.07L7.697 0h.605L15 4.465z"/></g><path class="st2" d="M8 1L2 5v6l6 4 6-4V5L8 1zm0 1.201l4.648 3.1-1.892 1.261-4.654-3.095L8 2.201zm-.5 11.264l-4.5-3v-1.53l4.5 3v1.53zm0-2.733l-4.5-3V6.268l4.5 3v1.464zM3.353 5.301l1.849-1.232 4.653 3.094L8 8.398 3.353 5.301zM13 10.465l-4.5 3v-1.53l4.5-3v1.53zm0-2.733l-4.5 3V9.268l4.5-3v1.464z" id="icon_x5F_bg"/><g id="icon_x5F_fg"><path class="st3" d="M8 2.201l4.648 3.1-1.892 1.261-4.654-3.095zM7.5 13.465l-4.5-3v-1.53l4.5 3zM7.5 10.732l-4.5-3V6.268l4.5 3zM3.353 5.301l1.848-1.233 4.653 3.094L8 8.398zM13 10.465l-4.5 3v-1.53l4.5-3zM13 7.732l-4.5 3V9.268l4.5-3z"/></g></svg>
\ No newline at end of file
diff --git a/ILSpy/Images/Metadata.xaml b/ILSpy/Images/Metadata.xaml
new file mode 100644
index 0000000000..53d0ab957f
--- /dev/null
+++ b/ILSpy/Images/Metadata.xaml
@@ -0,0 +1,15 @@
+<!-- This file was generated by the AiToXaml tool.-->
+<!-- Tool Version: 14.0.22307.0 -->
+<DrawingGroup xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
+  <DrawingGroup.Children>
+    <GeometryDrawing Brush="#00FFFFFF" Geometry="F1M16,16L0,16 0,0 16,0z" />
+    <GeometryDrawing Brush="#FFF6F6F6" Geometry="F1M7.6977,-0.000199999999999534L0.9997,4.4648 0.9997,11.5348 7.6977,15.9998 8.3027,15.9998 15.0007,11.5348 15.0007,4.4648 8.3027,-0.000199999999999534z" />
+    <GeometryDrawing Brush="#FF414141" Geometry="F1M13,7.7324L8.5,10.7324 8.5,9.2674 13,6.2674z M13,10.4644L8.5,13.4644 8.5,11.9344 13,8.9344z M3.353,5.3004L5.201,4.0684 9.854,7.1624 8,8.3984z M7.5,10.7324L3,7.7324 3,6.2674 7.5,9.2674z M7.5,13.4644L3,10.4644 3,8.9344 7.5,11.9344z M8,2.2014L12.647,5.3004 10.756,6.5614 6.102,3.4664z M8,1.0004L2,5.0004 2,11.0004 8,15.0004 14,11.0004 14,5.0004z" />
+    <GeometryDrawing Brush="#FFF0EFF1" Geometry="F1M8,2.2012L12.647,5.3012 10.756,6.5612 6.102,3.4672z" />
+    <GeometryDrawing Brush="#FFF0EFF1" Geometry="F1M7.5,13.4648L3,10.4648 3,8.9348 7.5,11.9348z" />
+    <GeometryDrawing Brush="#FFF0EFF1" Geometry="F1M7.5,10.7324L3,7.7324 3,6.2674 7.5,9.2674z" />
+    <GeometryDrawing Brush="#FFF0EFF1" Geometry="F1M3.3525,5.3008L5.2015,4.0688 9.8545,7.1618 7.9995,8.3988z" />
+    <GeometryDrawing Brush="#FFF0EFF1" Geometry="F1M13,10.4648L8.5,13.4648 8.5,11.9348 13,8.9348z" />
+    <GeometryDrawing Brush="#FFF0EFF1" Geometry="F1M13,7.7324L8.5,10.7324 8.5,9.2674 13,6.2674z" />
+  </DrawingGroup.Children>
+</DrawingGroup>
\ No newline at end of file
diff --git a/ILSpy/Images/MetadataFile.svg b/ILSpy/Images/MetadataFile.svg
new file mode 100644
index 0000000000..ce9cb449ed
--- /dev/null
+++ b/ILSpy/Images/MetadataFile.svg
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   viewBox="0 0 16 16"
+   version="1.1"
+   id="svg4"
+   sodipodi:docname="MetadataFile.svg"
+   xml:space="preserve"
+   inkscape:version="1.3.1 (91b66b0783, 2023-11-16)"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg"><defs
+     id="defs4" /><sodipodi:namedview
+     id="namedview4"
+     pagecolor="#ffffff"
+     bordercolor="#000000"
+     borderopacity="0.25"
+     inkscape:showpageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:deskcolor="#d1d1d1"
+     inkscape:zoom="12.828125"
+     inkscape:cx="24.672351"
+     inkscape:cy="7.6004872"
+     inkscape:window-width="1920"
+     inkscape:window-height="1017"
+     inkscape:window-x="-8"
+     inkscape:window-y="-8"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="svg4" /><style
+     id="style1">.st0{opacity:0}.st0,.st1{fill:#f6f6f6}.st2{fill:#424242}.st3{fill:#f0eff1}</style><g
+     id="outline"
+     style="display:inline"><path
+       class="st0"
+       d="M 0,0 H 16 V 16 H 0 Z"
+       id="path1"
+       style="display:inline" /><path
+       class="st1"
+       d="M 10.023,1 H 3.964 C 3.012,1 2,1.701 2,3 V 8.556 C 0.81,9.25 0,10.525 0,12 c 0,2.206 1.794,4 4,4 a 3.971,3.971 0 0 0 2.618,-1 h 5.347 C 13.407,15 13.972,13.825 14,13 V 4.552 Z"
+       id="path2"
+       style="display:inline" /></g><g
+     id="icon_x5F_bg"><path
+       class="st2"
+       d="M 6,6 H 8 V 7 H 6 Z M 6,8 V 8.555 C 6.222,8.684 6.428,8.832 6.62,9 H 10 V 8 Z m 1.858,3 H 10 V 10 H 7.445 c 0.181,0.311 0.321,0.644 0.413,1 z"
+       id="path3"
+       style="display:inline" /><path
+       class="st2"
+       d="M 9.641,2 H 3.964 C 3.964,2 3,2 3,3 V 8.142 A 3.978,3.978 0 0 1 4,8 V 3 h 5 v 3 h 3 v 7 H 7.858 a 3.945,3.945 0 0 1 -0.414,1 h 4.521 C 12.965,14 13,13 13,13 V 5 Z"
+       id="path4"
+       style="display:inline" /></g><path
+     class="st3"
+     d="M9 6V3H4v5c.735 0 1.417.213 2.009.562L6 8.555V8h4v1H6.62c-.005-.005-.012-.008-.018-.013.344.298.633.649.86 1.047-.006-.011-.01-.023-.017-.034H10v1H7.858l-.005-.017c.086.328.147.663.147 1.017 0 .348-.059.679-.142 1H12V6H9zM8 7H6V6h2v1z"
+     id="icon_x5F_fg" /><style
+     id="style1-9">.st0{opacity:0}.st0,.st1{fill:#f6f6f6}.st2{fill:#424242}.st3{fill:#f0eff1}</style><style
+     type="text/css"
+     id="style1-2">.icon-canvas-transparent{opacity:0;fill:#F6F6F6;} .icon-vs-out{fill:#F6F6F6;} .icon-vs-fg{fill:#F0EFF1;} .icon-vs-bg{fill:#424242;}</style><g
+     id="g4"
+     transform="matrix(0.5,0,0,0.5,0,8)"
+     style="display:inline"><g
+       id="outline-9"><path
+         class="st0"
+         d="M 0,0 H 16 V 16 H 0 Z"
+         id="path1-3" /><path
+         class="st1"
+         d="m 15,4.465 v 7.07 L 8.303,16 H 7.697 L 1,11.535 V 4.465 L 7.697,0 h 0.605 z"
+         id="path2-8" /></g><path
+       class="st2"
+       d="M 8,1 2,5 v 6 l 6,4 6,-4 V 5 Z m 0,1.201 4.648,3.1 -1.892,1.261 -4.654,-3.095 z m -0.5,11.264 -4.5,-3 v -1.53 l 4.5,3 z m 0,-2.733 -4.5,-3 V 6.268 l 4.5,3 z M 3.353,5.301 5.202,4.069 9.855,7.163 8,8.398 Z m 9.647,5.164 -4.5,3 v -1.53 l 4.5,-3 z m 0,-2.733 -4.5,3 V 9.268 l 4.5,-3 z"
+       id="icon_x5F_bg-2" /><g
+       id="icon_x5F_fg-1"><path
+         class="st3"
+         d="m 8,2.201 4.648,3.1 -1.892,1.261 -4.654,-3.095 z m -0.5,11.264 -4.5,-3 v -1.53 l 4.5,3 z m 0,-2.733 -4.5,-3 V 6.268 l 4.5,3 z M 3.353,5.301 5.201,4.068 9.854,7.162 8,8.398 Z m 9.647,5.164 -4.5,3 v -1.53 l 4.5,-3 z m 0,-2.733 -4.5,3 V 9.268 l 4.5,-3 z"
+         id="path3-0" /></g></g></svg>
diff --git a/ILSpy/Images/MetadataFile.xaml b/ILSpy/Images/MetadataFile.xaml
new file mode 100644
index 0000000000..5122e7d207
--- /dev/null
+++ b/ILSpy/Images/MetadataFile.xaml
@@ -0,0 +1,29 @@
+<DrawingGroup xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" ClipGeometry="M0,0 V16 H16 V0 H0 Z">
+  <DrawingGroup Opacity="1">
+    <GeometryDrawing Geometry="F1 M16,16z M0,0z M0,0L16,0 16,16 0,16z">
+      <GeometryDrawing.Brush>
+        <SolidColorBrush Color="#FFF6F6F6" Opacity="0" />
+      </GeometryDrawing.Brush>
+    </GeometryDrawing>
+    <GeometryDrawing Brush="#FFF6F6F6" Geometry="F1 M16,16z M0,0z M10.023,1L3.964,1C3.012,1,2,1.701,2,3L2,8.556C0.81,9.25 0,10.525 0,12 0,14.206 1.794,16 4,16A3.971,3.971,0,0,0,6.618,15L11.965,15C13.407,15,13.972,13.825,14,13L14,4.552z" />
+  </DrawingGroup>
+  <DrawingGroup Opacity="1">
+    <GeometryDrawing Brush="#FF424242" Geometry="F1 M16,16z M0,0z M6,6L8,6 8,7 6,7z M6,8L6,8.555C6.222,8.684,6.428,8.832,6.62,9L10,9 10,8z M7.858,11L10,11 10,10 7.445,10C7.626,10.311,7.766,10.644,7.858,11z" />
+    <GeometryDrawing Brush="#FF424242" Geometry="F1 M16,16z M0,0z M9.641,2L3.964,2C3.964,2,3,2,3,3L3,8.142A3.978,3.978,0,0,1,4,8L4,3 9,3 9,6 12,6 12,13 7.858,13A3.945,3.945,0,0,1,7.444,14L11.965,14C12.965,14,13,13,13,13L13,5z" />
+  </DrawingGroup>
+  <GeometryDrawing Brush="#FFF0EFF1" Geometry="F1 M16,16z M0,0z M9,6L9,3 4,3 4,8C4.735,8,5.417,8.213,6.009,8.562L6,8.555 6,8 10,8 10,9 6.62,9C6.615,8.995 6.608,8.992 6.602,8.987 6.946,9.285 7.235,9.636 7.462,10.034 7.456,10.023 7.452,10.011 7.445,10L10,10 10,11 7.858,11 7.853,10.983C7.939,11.311 8,11.646 8,12 8,12.348 7.941,12.679 7.858,13L12,13 12,6 9,6z M8,7L6,7 6,6 8,6 8,7z" />
+  <DrawingGroup Opacity="1" Transform="0.5,0,0,0.5,0,8">
+    <DrawingGroup Opacity="1">
+      <GeometryDrawing Geometry="F1 M16,16z M0,0z M0,0L16,0 16,16 0,16z">
+        <GeometryDrawing.Brush>
+          <SolidColorBrush Color="#FFF6F6F6" Opacity="0" />
+        </GeometryDrawing.Brush>
+      </GeometryDrawing>
+      <GeometryDrawing Brush="#FFF6F6F6" Geometry="F1 M16,16z M0,0z M15,4.465L15,11.535 8.303,16 7.697,16 1,11.535 1,4.465 7.697,0 8.302,0z" />
+    </DrawingGroup>
+    <GeometryDrawing Brush="#FF424242" Geometry="F1 M16,16z M0,0z M8,1L2,5 2,11 8,15 14,11 14,5z M8,2.201L12.648,5.301 10.756,6.562 6.102,3.467z M7.5,13.465L3,10.465 3,8.935 7.5,11.935z M7.5,10.732L3,7.732 3,6.268 7.5,9.268z M3.353,5.301L5.202,4.069 9.855,7.163 8,8.398z M13,10.465L8.5,13.465 8.5,11.935 13,8.935z M13,7.732L8.5,10.732 8.5,9.268 13,6.268z" />
+    <DrawingGroup Opacity="1">
+      <GeometryDrawing Brush="#FFF0EFF1" Geometry="F1 M16,16z M0,0z M8,2.201L12.648,5.301 10.756,6.562 6.102,3.467z M7.5,13.465L3,10.465 3,8.935 7.5,11.935z M7.5,10.732L3,7.732 3,6.268 7.5,9.268z M3.353,5.301L5.201,4.068 9.854,7.162 8,8.398z M13,10.465L8.5,13.465 8.5,11.935 13,8.935z M13,7.732L8.5,10.732 8.5,9.268 13,6.268z" />
+    </DrawingGroup>
+  </DrawingGroup>
+</DrawingGroup>
\ No newline at end of file
diff --git a/ILSpy/Images/MetadataTable.svg b/ILSpy/Images/MetadataTable.svg
new file mode 100644
index 0000000000..b333a0a257
--- /dev/null
+++ b/ILSpy/Images/MetadataTable.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-bg{fill:#424242}.icon-vs-fg{fill:#f0eff1}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M16 1v14h-4.78c-.55.609-1.337 1-2.22 1H5c-.884 0-1.674-.39-2.223-1H1v-1.796A2.977 2.977 0 0 1 0 11c0-.883.391-1.67 1-2.22V1h15z" id="outline"/><path class="icon-vs-fg" d="M7 8h3v2h-.174A3.004 3.004 0 0 0 7 8zm0-1h3V5H7v2zM3 7h3V5H3v2zm8-2v2h3V5h-3zm1 8h2v-2h-2.798c.497.544.798 1.249.798 2zm-1-3h3V8h-3v2z" id="iconFg"/><g id="iconBg"><path class="icon-vs-bg" d="M15 2v12h-3.184c.112-.314.184-.648.184-1h2v-2h-2.798a2.996 2.996 0 0 0-.738-.607l-.621-.35c-.004-.015-.012-.028-.017-.043H10V8H3c-.352 0-.686.072-1 .184V2h13zM6 5H3v2h3V5zm4 0H7v2h3V5zm4 3h-3v2h3V8zm0-3h-3v2h3V5zm-4.027 6.264a2.965 2.965 0 0 1-.275 1.024A.99.99 0 0 1 10 13a1 1 0 0 1-1 1H5a1.001 1.001 0 0 1 0-2l1-1H5c-1.103 0-2 .897-2 2 0 1.102.897 2 2 2h4c1.102 0 2-.898 2-2 0-.748-.417-1.393-1.027-1.736zM3 10h4a1.001 1.001 0 0 1 0 2l-1 1h1c1.102 0 2-.897 2-2s-.898-2-2-2H3c-1.103 0-2 .897-2 2 0 .748.417 1.393 1.027 1.736a2.96 2.96 0 0 1 .275-1.024A.99.99 0 0 1 2 11c0-.551.449-1 1-1z"/></g></svg>
\ No newline at end of file
diff --git a/ILSpy/Images/MetadataTable.xaml b/ILSpy/Images/MetadataTable.xaml
new file mode 100644
index 0000000000..4866c51a2a
--- /dev/null
+++ b/ILSpy/Images/MetadataTable.xaml
@@ -0,0 +1,10 @@
+<!-- This file was generated by the AiToXaml tool.-->
+<!-- Tool Version: 14.0.22307.0 -->
+<DrawingGroup xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
+  <DrawingGroup.Children>
+    <GeometryDrawing Brush="#00FFFFFF" Geometry="F1M16,16L0,16 0,0 16,0z" />
+    <GeometryDrawing Brush="#FFF6F6F6" Geometry="F1M16,1L16,15 11.22,15C10.67,15.609,9.883,16,9,16L5,16C4.116,16,3.326,15.61,2.776,15L1,15 1,13.204C0.378,12.643 0,11.851 0,11 0,10.117 0.391,9.33 1,8.78L1,1z" />
+    <GeometryDrawing Brush="#FFEFEFF0" Geometry="F1M11,10L14,10 14,8 11,8z M12,13L14,13 14,11 11.202,11C11.699,11.544,12,12.249,12,13 M11,7L14,7 14,5 11,5z M3,7L6,7 6,5 3,5z M7,7L10,7 10,5 7,5z M7,8L10,8 10,10 9.826,10C9.412,8.837,8.303,8,7,8" />
+    <GeometryDrawing Brush="#FF424242" Geometry="F1M3,10L7,10C7.552,10 8,10.449 8,11 8,11.551 7.552,12 7,12L6,13 7,13C8.103,13 9,12.104 9,11 9,9.896 8.103,9 7,9L3,9C1.897,9 1,9.896 1,11 1,11.748 1.417,12.394 2.027,12.736 2.059,12.372 2.15,12.027 2.302,11.713 2.116,11.531 2,11.279 2,11 2,10.449 2.449,10 3,10 M9.974,11.264C9.941,11.628 9.85,11.973 9.698,12.287 9.884,12.469 10,12.721 10,13 10,13.552 9.552,14 9,14L5,14C4.449,14 4,13.552 4,13 4,12.449 4.449,12 5,12L6,11 5,11C3.897,11 3,11.896 3,13 3,14.103 3.897,15 5,15L9,15C10.103,15 11,14.103 11,13 11,12.252 10.583,11.606 9.974,11.264 M14,5L11,5 11,7 14,7z M14,8L11,8 11,10 14,10z M10,5L7,5 7,7 10,7z M6,5L3,5 3,7 6,7z M15,2L15,14 11.815,14C11.928,13.686,12,13.353,12,13L14,13 14,11 11.202,11C10.988,10.766,10.75,10.553,10.465,10.393L9.844,10.043C9.839,10.027,9.831,10.015,9.826,10L10,10 10,8 7,8 6,8 3,8C2.647,8,2.314,8.072,2,8.184L2,2z" />
+  </DrawingGroup.Children>
+</DrawingGroup>
\ No newline at end of file
diff --git a/ILSpy/Images/MetadataTableGroup.svg b/ILSpy/Images/MetadataTableGroup.svg
new file mode 100644
index 0000000000..9af5cdc536
--- /dev/null
+++ b/ILSpy/Images/MetadataTableGroup.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-bg{fill:#424242}.icon-vs-fg{fill:#f0eff1}</style><path class="icon-canvas-transparent" d="M16 0v16H0V0h16z" id="canvas"/><path class="icon-vs-out" d="M16 6v10H4v-3H0V3h3V0h12v6h1z" id="outline"/><path class="icon-vs-bg" d="M2 7h2v1H2v1h2v1H2v1h2v1H1V4h10v2H2v1zm11-3h-1v1h1v1h1V1H4v2h9v1zm2 3v8H5V7h10zm-7 6H6v1h2v-1zm0-2H6v1h2v-1zm0-2H6v1h2V9zm3 4H9v1h2v-1zm0-2H9v1h2v-1zm0-2H9v1h2V9zm3 4h-2v1h2v-1zm0-2h-2v1h2v-1zm0-2h-2v1h2V9z" id="iconBg"/><g id="iconFg"><path class="icon-vs-fg" d="M2 6h2v1H2V6zm0 3h2V8H2v1zm4 5h2v-1H6v1zm7-9h-1v1h1V5zm0-2h-1v1h1V3zM2 11h2v-1H2v1zm4 1h2v-1H6v1zm3 2h2v-1H9v1zm-3-4h2V9H6v1zm6 4h2v-1h-2v1zm0-5v1h2V9h-2zm0 3h2v-1h-2v1zm-3 0h2v-1H9v1zm0-2h2V9H9v1z"/></g></svg>
\ No newline at end of file
diff --git a/ILSpy/Images/MetadataTableGroup.xaml b/ILSpy/Images/MetadataTableGroup.xaml
new file mode 100644
index 0000000000..df2cc7490c
--- /dev/null
+++ b/ILSpy/Images/MetadataTableGroup.xaml
@@ -0,0 +1,10 @@
+<!-- This file was generated by the AiToXaml tool.-->
+<!-- Tool Version: 14.0.22307.0 -->
+<DrawingGroup xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
+  <DrawingGroup.Children>
+    <GeometryDrawing Brush="#00FFFFFF" Geometry="F1M16,16L0,16 0,0 16,0z" />
+    <GeometryDrawing Brush="#FFF6F6F6" Geometry="F1M2.9997,-0.000199999999999534L2.9997,3.0008 -0.000300000000000189,3.0008 -0.000300000000000189,13.0008 3.9997,13.0008 3.9997,15.9998 16.0007,15.9998 16.0007,5.9998 15.0007,5.9998 15.0007,-0.000199999999999534z" />
+    <GeometryDrawing Brush="#FF424242" Geometry="F1M14,9L12,9 12,10 14,10z M14,11L12,11 12,12 14,12z M14,13L12,13 12,14 14,14z M11,9L9,9 9,10 11,10z M11,11L9,11 9,12 11,12z M11,13L9,13 9,14 11,14z M8,9L6,9 6,10 8,10z M8,11L6,11 6,12 8,12z M8,13L6,13 6,14 8,14z M15,15L5,15 5,7 15,7z M13,4L12,4 12,5 13,5 13,6 14,6 14,1 4,1 4,3 13,3z M2,7L4,7 4,8 2,8 2,9 4,9 4,10 2,10 2,11 4,11 4,12 1,12 1,4 11,4 11,6 2,6z" />
+    <GeometryDrawing Brush="#FFEFEFF0" Geometry="F1M9,10L11,10 11,9 9,9z M9,12L11,12 11,11 9,11z M12,12L14,12 14,11 12,11z M12,10L14,10 14,9 12,9z M12,14L14,14 14,13 12,13z M6,10L8,10 8,9 6,9z M9,14L11,14 11,13 9,13z M6,12L8,12 8,11 6,11z M2,11L4,11 4,10 2,10z M13,3L12,3 12,4 13,4z M13,5L12,5 12,6 13,6z M6,14L8,14 8,13 6,13z M2,9L4,9 4,8 2,8z M2,6L4,6 4,7 2,7z" />
+  </DrawingGroup.Children>
+</DrawingGroup>
\ No newline at end of file
diff --git a/ILSpy/Images/ProgramDebugDatabase.svg b/ILSpy/Images/ProgramDebugDatabase.svg
new file mode 100644
index 0000000000..4c4e7b2415
--- /dev/null
+++ b/ILSpy/Images/ProgramDebugDatabase.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.st0{opacity:0}.st0,.st1{fill:#f6f6f6}.st2{fill:#424242}.st3{fill:#f0eff1}</style><g id="outline"><path class="st0" d="M0 0h16v16H0z"/><path class="st1" d="M10.023 1H3.964C3.012 1 2 1.701 2 3v5.556C.81 9.25 0 10.525 0 12c0 2.206 1.794 4 4 4a3.971 3.971 0 0 0 2.618-1h5.347c1.442 0 2.007-1.175 2.035-2V4.552L10.023 1z"/></g><g id="icon_x5F_bg"><path class="st2" d="M6 6h2v1H6zM6 8v.555c.222.129.428.277.62.445H10V8H6zM7.858 11H10v-1H7.445c.181.311.321.644.413 1z"/><circle class="st2" cx="4" cy="12" r="3"/><path class="st2" d="M9.641 2H3.964S3 2 3 3v5.142A3.978 3.978 0 0 1 4 8V3h5v3h3v7H7.858a3.945 3.945 0 0 1-.414 1h4.521c1 0 1.035-1 1.035-1V5L9.641 2z"/></g><path class="st3" d="M9 6V3H4v5c.735 0 1.417.213 2.009.562L6 8.555V8h4v1H6.62c-.005-.005-.012-.008-.018-.013.344.298.633.649.86 1.047-.006-.011-.01-.023-.017-.034H10v1H7.858l-.005-.017c.086.328.147.663.147 1.017 0 .348-.059.679-.142 1H12V6H9zM8 7H6V6h2v1z" id="icon_x5F_fg"/></svg>
\ No newline at end of file
diff --git a/ILSpy/Images/ProgramDebugDatabase.xaml b/ILSpy/Images/ProgramDebugDatabase.xaml
new file mode 100644
index 0000000000..098b63518e
--- /dev/null
+++ b/ILSpy/Images/ProgramDebugDatabase.xaml
@@ -0,0 +1,14 @@
+<!-- This file was generated by the AiToXaml tool.-->
+<!-- Tool Version: 14.0.22307.0 -->
+<DrawingGroup xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" ClipGeometry="M0,0 V16 H16 V0 H0 Z">
+  <DrawingGroup.Children>
+    <GeometryDrawing Brush="#00FFFFFF" Geometry="F1M16,16L0,16 0,0 16,0z" />
+    <GeometryDrawing Brush="#FFF6F6F6" Geometry="F1M10.0225,1L3.9635,1C3.0115,1,2.0005,1.701,2.0005,3L2.0005,8.556C0.810500000000001,9.25 0.000500000000000611,10.525 0.000500000000000611,12 0.000500000000000611,14.206 1.7945,16 4.0005,16 5.0055,16 5.9145,15.614 6.6175,15L11.9645,15C13.4075,15,13.9715,13.825,14.0005,13L14.0005,4.552z" />
+    <GeometryDrawing Brush="#FF414141" Geometry="F1M6,7L8,7 8,6 6,6z" />
+    <GeometryDrawing Brush="#FF414141" Geometry="F1M6,8L6,8.555C6.222,8.684,6.428,8.832,6.62,9L10,9 10,8z" />
+    <GeometryDrawing Brush="#FF414141" Geometry="F1M7.8584,11L10.0004,11 10.0004,10 7.4454,10C7.6264,10.311,7.7664,10.644,7.8584,11" />
+    <GeometryDrawing Brush="#FF414141" Geometry="F1M7,12C7,10.344 5.657,9 4,9 2.343,9 1,10.344 1,12 1,13.656 2.343,15 4,15 5.657,15 7,13.656 7,12" />
+    <GeometryDrawing Brush="#FF414141" Geometry="F1M9.6406,2L3.9636,2C3.9636,2,2.9996,2,2.9996,3L2.9996,8.142C3.3216,8.059,3.6526,8,3.9996,8L3.9996,3 8.9996,3 8.9996,6 11.9996,6 11.9996,13 7.8576,13C7.7656,13.355,7.6246,13.689,7.4436,14L11.9646,14C12.9646,14,12.9996,13,12.9996,13L12.9996,5z" />
+    <GeometryDrawing Brush="#FFF0EFF1" Geometry="F1M8,7L6,7 6,6 8,6z M9,6L9,3 4,3 4,8C4.735,8 5.417,8.213 6.009,8.562 6.006,8.56 6.003,8.557 6,8.555L6,8 10,8 10,9 6.62,9C6.615,8.995 6.608,8.992 6.602,8.987 6.946,9.285 7.235,9.637 7.462,10.034 7.456,10.023 7.452,10.011 7.445,10L10,10 10,11 7.858,11C7.857,10.994 7.854,10.989 7.853,10.983 7.939,11.311 8,11.646 8,12 8,12.348 7.941,12.679 7.858,13L12,13 12,6z" />
+  </DrawingGroup.Children>
+</DrawingGroup>
\ No newline at end of file
diff --git a/ILSpy/Images/README.md b/ILSpy/Images/README.md
index e258db4880..82decd3387 100644
--- a/ILSpy/Images/README.md
+++ b/ILSpy/Images/README.md
@@ -10,7 +10,7 @@ Icons used in ILSpy:
 | Back                      |  x  |  x   | VS 2017 Icon Pack (Backward)                                                    |         |
 | Class                     |  x  |  x   | VS 2017 Icon Pack (Class)                                                       |         |
 | Close                     |  x  |  x   | VS 2017 Icon Pack (Clear)                                                       |         |
-| CollapseAll               |  x  |  x   | VS 2017 Icon Pack (CollapseAll)                                                 |         | 
+| CollapseAll               |  x  |  x   | VS 2017 Icon Pack (CollapseAll)                                                 |         |
 | Constructor               |  x  |  x   | based on VS 2017 Icon Pack (Method) using a different colour                    |         |
 | Copy                      |  x  |  x   | VS 2017 Icon Pack (Copy)                                                        |         |
 | Delegate                  |  x  |  x   | VS 2017 Icon Pack (Delegate)                                                    |         |
@@ -25,10 +25,18 @@ Icons used in ILSpy:
 | Folder.Closed             |  x  |  x   | VS 2017 Icon Pack (Folder)                                                      |         |
 | Folder.Open               |  x  |  x   | VS 2017 Icon Pack (FolderOpen)                                                  |         |
 | Forward                   |  x  |  x   | VS 2017 Icon Pack (Forward)                                                     |         |
+| Header                    |  x  |  x   | VS 2017 Icon Pack (PageHeader)                                                  |         |
+| Heap                      |  x  |  x   | VS 2017 Icon Pack (Datalist)                                                    |         |
 | Indexer                   |  x  |  x   | VS 2017 Icon Pack (Indexer)                                                     |         |
 | Interface                 |  x  |  x   | VS 2017 Icon Pack (Interface)                                                   |         |
 | Library                   |  x  |  x   | VS 2017 Icon Pack (Library)                                                     |         |
+| ListFolder                |  x  |  x   | VS 2017 Icon Pack (ListFolder)                                                  |         |
+| ListFolder.Open           |  x  |  x   | VS 2017 Icon Pack (ListFolderOpen)                                              |         |
 | Literal                   |  x  |  x   | VS 2017 Icon Pack (Literal)                                                     |         |
+| Metadata                  |  x  |  x   | VS 2017 Icon Pack (Metadata)                                                    |         |
+| MetadataFile              |  x  |  x   | combined ProgramDebugDatabase + Metadata                                        |         |
+| MetadataTable             |  x  |  x   | VS 2017 Icon Pack (LinkedTable)                                                 |         |
+| MetadataTableGroup        |  x  |  x   | VS 2017 Icon Pack (LinkedTableGroup)                                            |         |
 | Method                    |  x  |  x   | VS 2017 Icon Pack (Method)                                                      |         |
 | Namespace                 |  x  |  x   | VS 2017 Icon Pack (Namespace)                                                   |         |
 | OK                        |  x  |  x   | VS 2017 Icon Pack (StatusOK)                                                    |         |
@@ -42,6 +50,7 @@ Icons used in ILSpy:
 | OverlayProtectedInternal  |  x  |  x   | combined OverlayProtected and OverlayInternal                                   |         |
 | OverlayStatic             |  x  |  x   | custom                                                                          |         |
 | PInvokeMethod             |  x  |  x   | based on VS 2017 Icon Pack (ExtensionMethod) with rotated arrow                 |         |
+| ProgramDebugDatabase      |  x  |  x   | VS 2017 Icon Pack (ProgramDebugDatabase)                                        |         |
 | Property                  |  x  |  x   | VS 2017 Icon Pack (Property)                                                    |         |
 | ReferenceFolder           |  x  |  x   | combined VS 2017 Icon Pack (Reference) two times                                |         |
 | Refresh                   |  x  |  x   | VS 2017 Icon Pack (Refresh)                                                     |         |
diff --git a/ILSpy/Metadata/CoffHeaderTreeNode.cs b/ILSpy/Metadata/CoffHeaderTreeNode.cs
index d7c25fa858..bcce1ef1a4 100644
--- a/ILSpy/Metadata/CoffHeaderTreeNode.cs
+++ b/ILSpy/Metadata/CoffHeaderTreeNode.cs
@@ -41,7 +41,7 @@ public CoffHeaderTreeNode(PEFile module)
 
 		public override object Text => "COFF Header";
 
-		public override object Icon => Images.Literal;
+		public override object Icon => Images.Header;
 
 		public override bool View(TabPageModel tabPage)
 		{
diff --git a/ILSpy/Metadata/CorTables/AssemblyRefTableTreeNode.cs b/ILSpy/Metadata/CorTables/AssemblyRefTableTreeNode.cs
index 41dff502c2..43cc98f869 100644
--- a/ILSpy/Metadata/CorTables/AssemblyRefTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/AssemblyRefTableTreeNode.cs
@@ -36,8 +36,6 @@ public AssemblyRefTableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"23 AssemblyRef ({metadataFile.Metadata.GetTableRowCount(TableIndex.AssemblyRef)})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/CorTables/AssemblyTableTreeNode.cs b/ILSpy/Metadata/CorTables/AssemblyTableTreeNode.cs
index b12c8cf3cc..f4f2f52ab5 100644
--- a/ILSpy/Metadata/CorTables/AssemblyTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/AssemblyTableTreeNode.cs
@@ -35,8 +35,6 @@ public AssemblyTableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"20 Assembly ({metadataFile.Metadata.GetTableRowCount(TableIndex.Assembly)})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/CorTables/ClassLayoutTableTreeNode.cs b/ILSpy/Metadata/CorTables/ClassLayoutTableTreeNode.cs
index a7191f2023..6607b16b51 100644
--- a/ILSpy/Metadata/CorTables/ClassLayoutTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/ClassLayoutTableTreeNode.cs
@@ -36,8 +36,6 @@ public ClassLayoutTableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"0F ClassLayout ({metadataFile.Metadata.GetTableRowCount(TableIndex.ClassLayout)})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/CorTables/ConstantTableTreeNode.cs b/ILSpy/Metadata/CorTables/ConstantTableTreeNode.cs
index dd45da5af3..f51aa9a85c 100644
--- a/ILSpy/Metadata/CorTables/ConstantTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/ConstantTableTreeNode.cs
@@ -35,8 +35,6 @@ public ConstantTableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"0B Constant ({metadataFile.Metadata.GetTableRowCount(TableIndex.Constant)})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/CorTables/CustomAttributeTableTreeNode.cs b/ILSpy/Metadata/CorTables/CustomAttributeTableTreeNode.cs
index 976a013628..706a1f34ec 100644
--- a/ILSpy/Metadata/CorTables/CustomAttributeTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/CustomAttributeTableTreeNode.cs
@@ -34,8 +34,6 @@ public CustomAttributeTableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"0C CustomAttribute ({metadataFile.Metadata.GetTableRowCount(TableIndex.CustomAttribute)})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/CorTables/DeclSecurityTableTreeNode.cs b/ILSpy/Metadata/CorTables/DeclSecurityTableTreeNode.cs
index cb423bbb0f..b43a109fd5 100644
--- a/ILSpy/Metadata/CorTables/DeclSecurityTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/DeclSecurityTableTreeNode.cs
@@ -35,8 +35,6 @@ public DeclSecurityTableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"0E DeclSecurity ({metadataFile.Metadata.GetTableRowCount(TableIndex.DeclSecurity)})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/CorTables/EventMapTableTreeNode.cs b/ILSpy/Metadata/CorTables/EventMapTableTreeNode.cs
index 001440f145..d5b822b79b 100644
--- a/ILSpy/Metadata/CorTables/EventMapTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/EventMapTableTreeNode.cs
@@ -35,8 +35,6 @@ public EventMapTableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"12 EventMap ({metadataFile.Metadata.GetTableRowCount(TableIndex.EventMap)})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/CorTables/EventTableTreeNode.cs b/ILSpy/Metadata/CorTables/EventTableTreeNode.cs
index c53fdf8a10..6809520902 100644
--- a/ILSpy/Metadata/CorTables/EventTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/EventTableTreeNode.cs
@@ -37,8 +37,6 @@ public EventTableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"14 Event ({metadataFile.Metadata.GetTableRowCount(TableIndex.Event)})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/CorTables/ExportedTypeTableTreeNode.cs b/ILSpy/Metadata/CorTables/ExportedTypeTableTreeNode.cs
index 70b5470331..4cf0784658 100644
--- a/ILSpy/Metadata/CorTables/ExportedTypeTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/ExportedTypeTableTreeNode.cs
@@ -35,8 +35,6 @@ public ExportedTypeTableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"27 ExportedType ({metadataFile.Metadata.GetTableRowCount(TableIndex.ExportedType)})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/CorTables/FieldLayoutTableTreeNode.cs b/ILSpy/Metadata/CorTables/FieldLayoutTableTreeNode.cs
index 85a5acdc6d..38c41bff74 100644
--- a/ILSpy/Metadata/CorTables/FieldLayoutTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/FieldLayoutTableTreeNode.cs
@@ -36,8 +36,6 @@ public FieldLayoutTableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"10 FieldLayout ({metadataFile.Metadata.GetTableRowCount(TableIndex.FieldLayout)})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/CorTables/FieldMarshalTableTreeNode.cs b/ILSpy/Metadata/CorTables/FieldMarshalTableTreeNode.cs
index 6624d9bb52..db20911804 100644
--- a/ILSpy/Metadata/CorTables/FieldMarshalTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/FieldMarshalTableTreeNode.cs
@@ -35,8 +35,6 @@ public FieldMarshalTableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"0D FieldMarshal ({metadataFile.Metadata.GetTableRowCount(TableIndex.FieldMarshal)})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/CorTables/FieldTableTreeNode.cs b/ILSpy/Metadata/CorTables/FieldTableTreeNode.cs
index 2e48a1476e..16c3ca9d2a 100644
--- a/ILSpy/Metadata/CorTables/FieldTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/FieldTableTreeNode.cs
@@ -38,8 +38,6 @@ public FieldTableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"04 Field ({metadataFile.Metadata.GetTableRowCount(TableIndex.Field)})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/CorTables/FileTableTreeNode.cs b/ILSpy/Metadata/CorTables/FileTableTreeNode.cs
index 1d85d18c47..183c2a75f5 100644
--- a/ILSpy/Metadata/CorTables/FileTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/FileTableTreeNode.cs
@@ -34,8 +34,6 @@ public FileTableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"26 File ({metadataFile.Metadata.GetTableRowCount(TableIndex.File)})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/CorTables/GenericParamConstraintTableTreeNode.cs b/ILSpy/Metadata/CorTables/GenericParamConstraintTableTreeNode.cs
index cdc08a59a9..a65be0a872 100644
--- a/ILSpy/Metadata/CorTables/GenericParamConstraintTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/GenericParamConstraintTableTreeNode.cs
@@ -35,8 +35,6 @@ public GenericParamConstraintTableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"2C GenericParamConstraint ({metadataFile.Metadata.GetTableRowCount(TableIndex.GenericParamConstraint)})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/CorTables/GenericParamTableTreeNode.cs b/ILSpy/Metadata/CorTables/GenericParamTableTreeNode.cs
index 7b88c771b9..6d8ce43e90 100644
--- a/ILSpy/Metadata/CorTables/GenericParamTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/GenericParamTableTreeNode.cs
@@ -35,8 +35,6 @@ public GenericParamTableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"2A GenericParam ({metadataFile.Metadata.GetTableRowCount(TableIndex.GenericParam)})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/CorTables/ImplMapTableTreeNode.cs b/ILSpy/Metadata/CorTables/ImplMapTableTreeNode.cs
index a3aef6f7be..2976597b08 100644
--- a/ILSpy/Metadata/CorTables/ImplMapTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/ImplMapTableTreeNode.cs
@@ -38,8 +38,6 @@ public ImplMapTableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"1C ImplMap ({metadataFile.Metadata.GetTableRowCount(TableIndex.ImplMap)})";
 
-		public override object Icon => Images.Literal;
-
 
 
 		public override bool View(ViewModels.TabPageModel tabPage)
diff --git a/ILSpy/Metadata/CorTables/InterfaceImplTableTreeNode.cs b/ILSpy/Metadata/CorTables/InterfaceImplTableTreeNode.cs
index 334616e364..92cefd2c43 100644
--- a/ILSpy/Metadata/CorTables/InterfaceImplTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/InterfaceImplTableTreeNode.cs
@@ -35,8 +35,6 @@ public InterfaceImplTableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"09 InterfaceImpl ({metadataFile.Metadata.GetTableRowCount(TableIndex.InterfaceImpl)})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/CorTables/ManifestResourceTableTreeNode.cs b/ILSpy/Metadata/CorTables/ManifestResourceTableTreeNode.cs
index 997a8df436..1247899d7d 100644
--- a/ILSpy/Metadata/CorTables/ManifestResourceTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/ManifestResourceTableTreeNode.cs
@@ -35,8 +35,6 @@ public ManifestResourceTableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"28 ManifestResource ({metadataFile.Metadata.GetTableRowCount(TableIndex.ManifestResource)})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/CorTables/MemberRefTableTreeNode.cs b/ILSpy/Metadata/CorTables/MemberRefTableTreeNode.cs
index 1e0798292c..17d368a68a 100644
--- a/ILSpy/Metadata/CorTables/MemberRefTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/MemberRefTableTreeNode.cs
@@ -34,8 +34,6 @@ public MemberRefTableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"0A MemberRef ({metadataFile.Metadata.GetTableRowCount(TableIndex.MemberRef)})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/CorTables/MethodImplTableTreeNode.cs b/ILSpy/Metadata/CorTables/MethodImplTableTreeNode.cs
index 21dc983636..e694704803 100644
--- a/ILSpy/Metadata/CorTables/MethodImplTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/MethodImplTableTreeNode.cs
@@ -34,8 +34,6 @@ public MethodImplTableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"19 MethodImpl ({metadataFile.Metadata.GetTableRowCount(TableIndex.MethodImpl)})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/CorTables/MethodSemanticsTableTreeNode.cs b/ILSpy/Metadata/CorTables/MethodSemanticsTableTreeNode.cs
index 89277fd498..4234733671 100644
--- a/ILSpy/Metadata/CorTables/MethodSemanticsTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/MethodSemanticsTableTreeNode.cs
@@ -35,8 +35,6 @@ public MethodSemanticsTableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"18 MethodSemantics ({metadataFile.Metadata.GetTableRowCount(TableIndex.MethodSemantics)})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/CorTables/MethodSpecTableTreeNode.cs b/ILSpy/Metadata/CorTables/MethodSpecTableTreeNode.cs
index 571b90414c..64b6b5ee5f 100644
--- a/ILSpy/Metadata/CorTables/MethodSpecTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/MethodSpecTableTreeNode.cs
@@ -35,8 +35,6 @@ public MethodSpecTableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"2B MethodSpec ({metadataFile.Metadata.GetTableRowCount(TableIndex.MethodSpec)})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/CorTables/MethodTableTreeNode.cs b/ILSpy/Metadata/CorTables/MethodTableTreeNode.cs
index 2fc44383c2..eaa49d1d6c 100644
--- a/ILSpy/Metadata/CorTables/MethodTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/MethodTableTreeNode.cs
@@ -38,8 +38,6 @@ public MethodTableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"06 Method ({metadataFile.Metadata.GetTableRowCount(TableIndex.MethodDef)})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/CorTables/ModuleRefTableTreeNode.cs b/ILSpy/Metadata/CorTables/ModuleRefTableTreeNode.cs
index 26f63a88c0..8ef4ab4f6e 100644
--- a/ILSpy/Metadata/CorTables/ModuleRefTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/ModuleRefTableTreeNode.cs
@@ -34,8 +34,6 @@ public ModuleRefTableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"1A ModuleRef ({metadataFile.Metadata.GetTableRowCount(TableIndex.ModuleRef)})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/CorTables/ModuleTableTreeNode.cs b/ILSpy/Metadata/CorTables/ModuleTableTreeNode.cs
index edc8af029b..6073d85bbf 100644
--- a/ILSpy/Metadata/CorTables/ModuleTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/ModuleTableTreeNode.cs
@@ -34,8 +34,6 @@ public ModuleTableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"00 Module ({metadataFile.Metadata.GetTableRowCount(TableIndex.Module)})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/CorTables/NestedClassTableTreeNode.cs b/ILSpy/Metadata/CorTables/NestedClassTableTreeNode.cs
index a1fc91e8e1..d75043bfa2 100644
--- a/ILSpy/Metadata/CorTables/NestedClassTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/NestedClassTableTreeNode.cs
@@ -35,8 +35,6 @@ public NestedClassTableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"29 NestedClass ({metadataFile.Metadata.GetTableRowCount(TableIndex.NestedClass)})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/CorTables/ParamTableTreeNode.cs b/ILSpy/Metadata/CorTables/ParamTableTreeNode.cs
index 5c24f8bd5d..0d69aa9d18 100644
--- a/ILSpy/Metadata/CorTables/ParamTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/ParamTableTreeNode.cs
@@ -35,8 +35,6 @@ public ParamTableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"08 Param ({metadataFile.Metadata.GetTableRowCount(TableIndex.Param)})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/CorTables/PropertyMapTableTreeNode.cs b/ILSpy/Metadata/CorTables/PropertyMapTableTreeNode.cs
index d3bbd2385e..1a7897ae3a 100644
--- a/ILSpy/Metadata/CorTables/PropertyMapTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/PropertyMapTableTreeNode.cs
@@ -35,8 +35,6 @@ public PropertyMapTableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"15 PropertyMap ({metadataFile.Metadata.GetTableRowCount(TableIndex.PropertyMap)})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/CorTables/PropertyTableTreeNode.cs b/ILSpy/Metadata/CorTables/PropertyTableTreeNode.cs
index 9419181ca3..65209e85c0 100644
--- a/ILSpy/Metadata/CorTables/PropertyTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/PropertyTableTreeNode.cs
@@ -37,8 +37,6 @@ public PropertyTableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"17 Property ({metadataFile.Metadata.GetTableRowCount(TableIndex.Property)})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/CorTables/StandAloneSigTableTreeNode.cs b/ILSpy/Metadata/CorTables/StandAloneSigTableTreeNode.cs
index 08fba15791..476ace7441 100644
--- a/ILSpy/Metadata/CorTables/StandAloneSigTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/StandAloneSigTableTreeNode.cs
@@ -34,8 +34,6 @@ public StandAloneSigTableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"11 StandAloneSig ({metadataFile.Metadata.GetTableRowCount(TableIndex.StandAloneSig)})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/CorTables/TypeDefTableTreeNode.cs b/ILSpy/Metadata/CorTables/TypeDefTableTreeNode.cs
index b0b3ec3792..0155d1e53a 100644
--- a/ILSpy/Metadata/CorTables/TypeDefTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/TypeDefTableTreeNode.cs
@@ -39,8 +39,6 @@ public TypeDefTableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"02 TypeDef ({metadataFile.Metadata.GetTableRowCount(TableIndex.TypeDef)})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/CorTables/TypeRefTableTreeNode.cs b/ILSpy/Metadata/CorTables/TypeRefTableTreeNode.cs
index 42dfd85fbe..0f9e98ce23 100644
--- a/ILSpy/Metadata/CorTables/TypeRefTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/TypeRefTableTreeNode.cs
@@ -34,8 +34,6 @@ public TypeRefTableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"01 TypeRef ({metadataFile.Metadata.GetTableRowCount(TableIndex.TypeRef)})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/CorTables/TypeSpecTableTreeNode.cs b/ILSpy/Metadata/CorTables/TypeSpecTableTreeNode.cs
index b7e5f81df7..1f8fc2106b 100644
--- a/ILSpy/Metadata/CorTables/TypeSpecTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/TypeSpecTableTreeNode.cs
@@ -35,8 +35,6 @@ public TypeSpecTableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"1B TypeSpec ({metadataFile.Metadata.GetTableRowCount(TableIndex.TypeSpec)})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/DataDirectoriesTreeNode.cs b/ILSpy/Metadata/DataDirectoriesTreeNode.cs
index 879389674b..4746ec1a09 100644
--- a/ILSpy/Metadata/DataDirectoriesTreeNode.cs
+++ b/ILSpy/Metadata/DataDirectoriesTreeNode.cs
@@ -17,12 +17,9 @@
 // DEALINGS IN THE SOFTWARE.
 
 using System.Reflection.PortableExecutable;
-using System.Windows.Controls;
-using System.Windows.Data;
 
 using ICSharpCode.Decompiler;
 using ICSharpCode.Decompiler.Metadata;
-using ICSharpCode.ILSpy.TextView;
 using ICSharpCode.ILSpy.TreeNodes;
 
 namespace ICSharpCode.ILSpy.Metadata
@@ -38,7 +35,8 @@ public DataDirectoriesTreeNode(PEFile module)
 
 		public override object Text => "Data Directories";
 
-		public override object Icon => Images.Literal;
+		public override object Icon => Images.ListFolder;
+		public override object ExpandedIcon => Images.ListFolderOpen;
 
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
diff --git a/ILSpy/Metadata/DebugDirectory/CodeViewTreeNode.cs b/ILSpy/Metadata/DebugDirectory/CodeViewTreeNode.cs
index 5fdf81a906..63037ec101 100644
--- a/ILSpy/Metadata/DebugDirectory/CodeViewTreeNode.cs
+++ b/ILSpy/Metadata/DebugDirectory/CodeViewTreeNode.cs
@@ -21,7 +21,6 @@
 using System.Reflection.PortableExecutable;
 
 using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.Metadata;
 using ICSharpCode.ILSpy.TreeNodes;
 using ICSharpCode.ILSpy.ViewModels;
 
@@ -39,7 +38,7 @@ public CodeViewTreeNode(CodeViewDebugDirectoryData entry)
 
 		public override object ToolTip => "Associated PDB file description.";
 
-		public override object Icon => Images.Literal;
+		public override object Icon => Images.MetadataTable;
 
 		public override bool View(TabPageModel tabPage)
 		{
diff --git a/ILSpy/Metadata/DebugDirectory/DebugDirectoryEntryTreeNode.cs b/ILSpy/Metadata/DebugDirectory/DebugDirectoryEntryTreeNode.cs
index 995cc8a173..dd19b0a7c0 100644
--- a/ILSpy/Metadata/DebugDirectory/DebugDirectoryEntryTreeNode.cs
+++ b/ILSpy/Metadata/DebugDirectory/DebugDirectoryEntryTreeNode.cs
@@ -23,7 +23,6 @@
 using ICSharpCode.Decompiler;
 using ICSharpCode.Decompiler.Metadata;
 using ICSharpCode.ILSpy.TreeNodes;
-using ICSharpCode.ILSpy.ViewModels;
 
 namespace ICSharpCode.ILSpy.Metadata
 {
@@ -39,9 +38,9 @@ public DebugDirectoryEntryTreeNode(PEFile module, DebugDirectoryEntry entry)
 			this.entry = entry;
 		}
 
-		override public object Text => $"{entry.Type}";
+		override public object Text => entry.Type.ToString();
 
-		public override object Icon => Images.Literal;
+		public override object Icon => Images.MetadataTable;
 
 		public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
 		{
diff --git a/ILSpy/Metadata/DebugDirectory/PdbChecksumTreeNode.cs b/ILSpy/Metadata/DebugDirectory/PdbChecksumTreeNode.cs
index 13444518d9..40d16053bb 100644
--- a/ILSpy/Metadata/DebugDirectory/PdbChecksumTreeNode.cs
+++ b/ILSpy/Metadata/DebugDirectory/PdbChecksumTreeNode.cs
@@ -44,7 +44,7 @@ public override object ToolTip
 			 + "be present if multiple PDBs were produced during the build of the PE/COFF file\n"
 			 + "(for example, private and public symbols).";
 
-		public override object Icon => Images.Literal;
+		public override object Icon => Images.MetadataTable;
 
 		public override bool View(TabPageModel tabPage)
 		{
diff --git a/ILSpy/Metadata/DebugDirectoryTreeNode.cs b/ILSpy/Metadata/DebugDirectoryTreeNode.cs
index 0166113e9a..d5ee104358 100644
--- a/ILSpy/Metadata/DebugDirectoryTreeNode.cs
+++ b/ILSpy/Metadata/DebugDirectoryTreeNode.cs
@@ -39,7 +39,9 @@ public DebugDirectoryTreeNode(PEFile module)
 
 		public override object Text => "Debug Directory";
 
-		public override object Icon => Images.Literal;
+		public override object Icon => Images.ListFolder;
+		public override object ExpandedIcon => Images.ListFolderOpen;
+
 
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
diff --git a/ILSpy/Metadata/DebugMetadataTablesTreeNode.cs b/ILSpy/Metadata/DebugMetadataTablesTreeNode.cs
new file mode 100644
index 0000000000..af8dd974a0
--- /dev/null
+++ b/ILSpy/Metadata/DebugMetadataTablesTreeNode.cs
@@ -0,0 +1,77 @@
+// Copyright (c) 2021 AlphaSierraPapa for the SharpDevelop Team
+// 
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+// 
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System.Reflection.Metadata.Ecma335;
+
+using ICSharpCode.Decompiler;
+using ICSharpCode.Decompiler.Metadata;
+using ICSharpCode.ILSpy.TreeNodes;
+using ICSharpCode.ILSpy.ViewModels;
+
+namespace ICSharpCode.ILSpy.Metadata
+{
+	class DebugMetadataTablesTreeNode : ILSpyTreeNode
+	{
+		private MetadataFile metadataFile;
+
+		public DebugMetadataTablesTreeNode(MetadataFile metadataFile)
+		{
+			this.metadataFile = metadataFile;
+			this.LazyLoading = true;
+		}
+
+		public override object Text => "Tables";
+
+		public override object Icon => Images.MetadataTableGroup;
+
+		protected override void LoadChildren()
+		{
+			if (ShowTable(TableIndex.Document))
+				this.Children.Add(new DocumentTableTreeNode(metadataFile));
+			if (ShowTable(TableIndex.MethodDebugInformation))
+				this.Children.Add(new MethodDebugInformationTableTreeNode(metadataFile));
+			if (ShowTable(TableIndex.LocalScope))
+				this.Children.Add(new LocalScopeTableTreeNode(metadataFile));
+			if (ShowTable(TableIndex.LocalVariable))
+				this.Children.Add(new LocalVariableTableTreeNode(metadataFile));
+			if (ShowTable(TableIndex.LocalConstant))
+				this.Children.Add(new LocalConstantTableTreeNode(metadataFile));
+			if (ShowTable(TableIndex.ImportScope))
+				this.Children.Add(new ImportScopeTableTreeNode(metadataFile));
+			if (ShowTable(TableIndex.StateMachineMethod))
+				this.Children.Add(new StateMachineMethodTableTreeNode(metadataFile));
+			if (ShowTable(TableIndex.CustomDebugInformation))
+				this.Children.Add(new CustomDebugInformationTableTreeNode(metadataFile));
+
+			bool ShowTable(TableIndex table) => !MainWindow.Instance.CurrentDisplaySettings.HideEmptyMetadataTables || metadataFile.Metadata.GetTableRowCount(table) > 0;
+		}
+
+		public override bool View(TabPageModel tabPage)
+		{
+			tabPage.Title = Text.ToString();
+			tabPage.SupportsLanguageSwitching = false;
+
+			return false;
+		}
+
+		public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
+		{
+			language.WriteCommentLine(output, "Metadata Tables");
+		}
+	}
+}
diff --git a/ILSpy/Metadata/DebugTables/CustomDebugInformationTableTreeNode.cs b/ILSpy/Metadata/DebugTables/CustomDebugInformationTableTreeNode.cs
index cf8224673f..b7e19fa3d9 100644
--- a/ILSpy/Metadata/DebugTables/CustomDebugInformationTableTreeNode.cs
+++ b/ILSpy/Metadata/DebugTables/CustomDebugInformationTableTreeNode.cs
@@ -39,8 +39,6 @@ public CustomDebugInformationTableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"37 CustomDebugInformation ({metadataFile.Metadata.GetTableRowCount(TableIndex.CustomDebugInformation)})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/DebugTables/DocumentTableTreeNode.cs b/ILSpy/Metadata/DebugTables/DocumentTableTreeNode.cs
index 9a27eaa91e..877dafbe9b 100644
--- a/ILSpy/Metadata/DebugTables/DocumentTableTreeNode.cs
+++ b/ILSpy/Metadata/DebugTables/DocumentTableTreeNode.cs
@@ -36,8 +36,6 @@ public DocumentTableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"30 Document ({metadataFile.Metadata.GetTableRowCount(TableIndex.Document)})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/DebugTables/ImportScopeTableTreeNode.cs b/ILSpy/Metadata/DebugTables/ImportScopeTableTreeNode.cs
index 880d210455..b6b878aca2 100644
--- a/ILSpy/Metadata/DebugTables/ImportScopeTableTreeNode.cs
+++ b/ILSpy/Metadata/DebugTables/ImportScopeTableTreeNode.cs
@@ -34,8 +34,6 @@ public ImportScopeTableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"35 ImportScope ({metadataFile.Metadata.GetTableRowCount(TableIndex.ImportScope)})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/DebugTables/LocalConstantTableTreeNode.cs b/ILSpy/Metadata/DebugTables/LocalConstantTableTreeNode.cs
index 7bfb14e529..6075499e55 100644
--- a/ILSpy/Metadata/DebugTables/LocalConstantTableTreeNode.cs
+++ b/ILSpy/Metadata/DebugTables/LocalConstantTableTreeNode.cs
@@ -34,8 +34,6 @@ public LocalConstantTableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"34 LocalConstant ({metadataFile.Metadata.GetTableRowCount(TableIndex.LocalConstant)})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/DebugTables/LocalScopeTableTreeNode.cs b/ILSpy/Metadata/DebugTables/LocalScopeTableTreeNode.cs
index e41c6caba6..59b0d01e7e 100644
--- a/ILSpy/Metadata/DebugTables/LocalScopeTableTreeNode.cs
+++ b/ILSpy/Metadata/DebugTables/LocalScopeTableTreeNode.cs
@@ -35,8 +35,6 @@ public LocalScopeTableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"32 LocalScope ({metadataFile.Metadata.GetTableRowCount(TableIndex.LocalScope)})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/DebugTables/LocalVariableTableTreeNode.cs b/ILSpy/Metadata/DebugTables/LocalVariableTableTreeNode.cs
index 17f0721e14..978ecd499f 100644
--- a/ILSpy/Metadata/DebugTables/LocalVariableTableTreeNode.cs
+++ b/ILSpy/Metadata/DebugTables/LocalVariableTableTreeNode.cs
@@ -34,8 +34,6 @@ public LocalVariableTableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"33 LocalVariable ({metadataFile.Metadata.GetTableRowCount(TableIndex.LocalVariable)})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/DebugTables/MethodDebugInformationTableTreeNode.cs b/ILSpy/Metadata/DebugTables/MethodDebugInformationTableTreeNode.cs
index 06b56e62af..591e388f64 100644
--- a/ILSpy/Metadata/DebugTables/MethodDebugInformationTableTreeNode.cs
+++ b/ILSpy/Metadata/DebugTables/MethodDebugInformationTableTreeNode.cs
@@ -36,8 +36,6 @@ public MethodDebugInformationTableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"31 MethodDebugInformation ({metadataFile.Metadata.GetTableRowCount(TableIndex.MethodDebugInformation)})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/DebugTables/StateMachineMethodTableTreeNode.cs b/ILSpy/Metadata/DebugTables/StateMachineMethodTableTreeNode.cs
index 8da97990a0..8882adbdd6 100644
--- a/ILSpy/Metadata/DebugTables/StateMachineMethodTableTreeNode.cs
+++ b/ILSpy/Metadata/DebugTables/StateMachineMethodTableTreeNode.cs
@@ -34,8 +34,6 @@ public StateMachineMethodTableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"36 StateMachineMethod ({metadataFile.Metadata.GetTableRowCount(TableIndex.StateMachineMethod)})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/DosHeaderTreeNode.cs b/ILSpy/Metadata/DosHeaderTreeNode.cs
index ad62e6fff9..29cb3833b4 100644
--- a/ILSpy/Metadata/DosHeaderTreeNode.cs
+++ b/ILSpy/Metadata/DosHeaderTreeNode.cs
@@ -17,8 +17,6 @@
 // DEALINGS IN THE SOFTWARE.
 
 using System.Collections.Generic;
-using System.Windows.Controls;
-using System.Windows.Data;
 
 using ICSharpCode.Decompiler;
 using ICSharpCode.Decompiler.Metadata;
@@ -38,7 +36,7 @@ public DosHeaderTreeNode(PEFile module)
 
 		public override object Text => "DOS Header";
 
-		public override object Icon => Images.Literal;
+		public override object Icon => Images.Header;
 
 		public override bool View(TabPageModel tabPage)
 		{
diff --git a/ILSpy/Metadata/Heaps/BlobHeapTreeNode.cs b/ILSpy/Metadata/Heaps/BlobHeapTreeNode.cs
index e1aa423647..7dc0c62b19 100644
--- a/ILSpy/Metadata/Heaps/BlobHeapTreeNode.cs
+++ b/ILSpy/Metadata/Heaps/BlobHeapTreeNode.cs
@@ -22,7 +22,6 @@
 
 using ICSharpCode.Decompiler;
 using ICSharpCode.Decompiler.Metadata;
-using ICSharpCode.ILSpyX;
 
 namespace ICSharpCode.ILSpy.Metadata
 {
@@ -47,8 +46,6 @@ public BlobHeapTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"Blob Heap ({list.Count})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/Heaps/GuidHeapTreeNode.cs b/ILSpy/Metadata/Heaps/GuidHeapTreeNode.cs
index 1aaa63c047..17de531ab1 100644
--- a/ILSpy/Metadata/Heaps/GuidHeapTreeNode.cs
+++ b/ILSpy/Metadata/Heaps/GuidHeapTreeNode.cs
@@ -44,8 +44,6 @@ public GuidHeapTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"Guid Heap ({list.Count})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/Heaps/StringHeapTreeNode.cs b/ILSpy/Metadata/Heaps/StringHeapTreeNode.cs
index ea6118ce6c..91f679de9c 100644
--- a/ILSpy/Metadata/Heaps/StringHeapTreeNode.cs
+++ b/ILSpy/Metadata/Heaps/StringHeapTreeNode.cs
@@ -45,8 +45,6 @@ public StringHeapTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"String Heap ({list.Count})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/Heaps/UserStringHeapTreeNode.cs b/ILSpy/Metadata/Heaps/UserStringHeapTreeNode.cs
index e9ee44a1ec..f2a7fd00d2 100644
--- a/ILSpy/Metadata/Heaps/UserStringHeapTreeNode.cs
+++ b/ILSpy/Metadata/Heaps/UserStringHeapTreeNode.cs
@@ -45,8 +45,6 @@ public UserStringHeapTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"UserString Heap ({list.Count})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();
diff --git a/ILSpy/Metadata/MetadataHeapTreeNode.cs b/ILSpy/Metadata/MetadataHeapTreeNode.cs
index 1e4cc7ea59..67a12036ad 100644
--- a/ILSpy/Metadata/MetadataHeapTreeNode.cs
+++ b/ILSpy/Metadata/MetadataHeapTreeNode.cs
@@ -32,17 +32,14 @@ internal abstract class MetadataHeapTreeNode : ILSpyTreeNode
 
 		public HandleKind Kind { get; }
 
+		public override object Icon => Images.Heap;
+
 		public MetadataHeapTreeNode(HandleKind kind, MetadataFile metadataFile)
 		{
 			this.Kind = kind;
 			this.metadataFile = metadataFile;
 		}
 
-		internal void ScrollTo(Handle handle)
-		{
-			//this.scrollTarget = MetadataTokens.GetHeapOffset((EntityHandle)handle);
-		}
-
 		protected void ScrollItemIntoView(DataGrid view, object item)
 		{
 			view.Loaded += View_Loaded;
diff --git a/ILSpy/Metadata/MetadataTableTreeNode.cs b/ILSpy/Metadata/MetadataTableTreeNode.cs
index 6978e1ec7d..54f2d47ae2 100644
--- a/ILSpy/Metadata/MetadataTableTreeNode.cs
+++ b/ILSpy/Metadata/MetadataTableTreeNode.cs
@@ -36,6 +36,8 @@ internal abstract class MetadataTableTreeNode : ILSpyTreeNode
 
 		public HandleKind Kind { get; }
 
+		public override object Icon => Images.MetadataTable;
+
 		public MetadataTableTreeNode(HandleKind kind, MetadataFile metadataFile)
 		{
 			this.Kind = kind;
diff --git a/ILSpy/Metadata/MetadataTablesTreeNode.cs b/ILSpy/Metadata/MetadataTablesTreeNode.cs
index e7b272b461..26bb59b211 100644
--- a/ILSpy/Metadata/MetadataTablesTreeNode.cs
+++ b/ILSpy/Metadata/MetadataTablesTreeNode.cs
@@ -39,7 +39,7 @@ public MetadataTablesTreeNode(MetadataFile metadataFile)
 
 		public override object Text => "Tables";
 
-		public override object Icon => Images.Literal;
+		public override object Icon => Images.MetadataTableGroup;
 
 		protected override void LoadChildren()
 		{
diff --git a/ILSpy/Metadata/MetadataTreeNode.cs b/ILSpy/Metadata/MetadataTreeNode.cs
index cbbd6d0a70..4aedf30a78 100644
--- a/ILSpy/Metadata/MetadataTreeNode.cs
+++ b/ILSpy/Metadata/MetadataTreeNode.cs
@@ -45,7 +45,7 @@ public MetadataTreeNode(MetadataFile module, string title)
 
 		public override object Text => title;
 
-		public override object Icon => Images.Library;
+		public override object Icon => Images.Metadata;
 
 		public override bool View(TabPageModel tabPage)
 		{
diff --git a/ILSpy/Metadata/OptionalHeaderTreeNode.cs b/ILSpy/Metadata/OptionalHeaderTreeNode.cs
index cbd67a2924..dc1be30ec7 100644
--- a/ILSpy/Metadata/OptionalHeaderTreeNode.cs
+++ b/ILSpy/Metadata/OptionalHeaderTreeNode.cs
@@ -40,7 +40,7 @@ public OptionalHeaderTreeNode(PEFile module)
 
 		public override object Text => "Optional Header";
 
-		public override object Icon => Images.Literal;
+		public override object Icon => Images.Header;
 
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
diff --git a/ILSpy/TreeNodes/AssemblyTreeNode.cs b/ILSpy/TreeNodes/AssemblyTreeNode.cs
index 7f32ea8951..fa692d2841 100644
--- a/ILSpy/TreeNodes/AssemblyTreeNode.cs
+++ b/ILSpy/TreeNodes/AssemblyTreeNode.cs
@@ -29,7 +29,7 @@
 using ICSharpCode.Decompiler.CSharp.ProjectDecompiler;
 using ICSharpCode.Decompiler.Metadata;
 using ICSharpCode.Decompiler.TypeSystem;
-using ICSharpCode.ILSpy.Options;
+using ICSharpCode.ILSpy.Metadata;
 using ICSharpCode.ILSpy.Properties;
 using ICSharpCode.ILSpy.ViewModels;
 using ICSharpCode.ILSpyX;
@@ -98,7 +98,18 @@ public override object Icon {
 							_ => Images.Library,
 						};
 					}
-					return Images.Assembly;
+					if (loadResult.MetadataFile != null)
+					{
+						return loadResult.MetadataFile.Kind switch {
+							MetadataFile.MetadataFileKind.PortableExecutable => Images.Assembly,
+							MetadataFile.MetadataFileKind.ProgramDebugDatabase => Images.ProgramDebugDatabase,
+							_ => Images.MetadataFile,
+						};
+					}
+					else
+					{
+						return Images.Assembly;
+					}
 				}
 				else
 				{
@@ -383,6 +394,10 @@ void HandleException(Exception ex, string message)
 					output.WriteLine("// " + LoadedAssembly.FileName);
 					DecompilePackage(loadResult.Package, output);
 				}
+				else if (loadResult.MetadataFile != null)
+				{
+					output.WriteLine("// " + LoadedAssembly.FileName);
+				}
 				else
 				{
 					LoadedAssembly.GetPEFileOrNullAsync().GetAwaiter().GetResult();

From c821063cb662b430f54a66af4b8ecdc2d3c51794 Mon Sep 17 00:00:00 2001
From: Siegfried Pammer <siegfriedpammer@gmail.com>
Date: Mon, 1 Jan 2024 15:37:54 +0100
Subject: [PATCH 5/5] Fixup FieldRVATableTreeNode icon

---
 ILSpy/Metadata/CorTables/FieldRVATableTreeNode.cs | 2 --
 1 file changed, 2 deletions(-)

diff --git a/ILSpy/Metadata/CorTables/FieldRVATableTreeNode.cs b/ILSpy/Metadata/CorTables/FieldRVATableTreeNode.cs
index ac8c8fc2eb..43f6e738fe 100644
--- a/ILSpy/Metadata/CorTables/FieldRVATableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/FieldRVATableTreeNode.cs
@@ -36,8 +36,6 @@ public FieldRVATableTreeNode(MetadataFile metadataFile)
 
 		public override object Text => $"1D FieldRVA ({metadataFile.Metadata.GetTableRowCount(TableIndex.FieldRva)})";
 
-		public override object Icon => Images.Literal;
-
 		public override bool View(ViewModels.TabPageModel tabPage)
 		{
 			tabPage.Title = Text.ToString();