diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
index 5c4539d5a..36513a754 100644
--- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
+++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
@@ -98,6 +98,7 @@
+
diff --git a/ICSharpCode.Decompiler/Metadata/ModuleReferenceMetadata.cs b/ICSharpCode.Decompiler/Metadata/ModuleReferenceMetadata.cs
new file mode 100644
index 000000000..eee2078f8
--- /dev/null
+++ b/ICSharpCode.Decompiler/Metadata/ModuleReferenceMetadata.cs
@@ -0,0 +1,132 @@
+// Copyright (c) 2023 James May
+//
+// 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.
+
+#nullable enable
+
+using System;
+using System.Collections.Immutable;
+using System.Linq;
+using System.Reflection;
+using System.Reflection.Metadata;
+
+namespace ICSharpCode.Decompiler.Metadata
+{
+#if !VSADDIN
+ public class ModuleReferenceMetadata /* : IModuleReference*/
+ {
+ readonly ModuleReference entry;
+
+ public MetadataReader Metadata { get; }
+ public ModuleReferenceHandle Handle { get; }
+
+ string? name;
+ public string Name {
+ get {
+ if (name == null)
+ {
+ try
+ {
+ name = Metadata.GetString(entry.Name);
+ }
+ catch (BadImageFormatException)
+ {
+ name = $"AR:{Handle}";
+ }
+ }
+ return name;
+ }
+ }
+
+ ImmutableArray attributes;
+ public ImmutableArray Attributes {
+ get {
+ var value = attributes;
+ if (value.IsDefault)
+ {
+ value = entry.GetCustomAttributes().Select(Metadata.GetCustomAttribute).ToImmutableArray();
+ attributes = value;
+ }
+ return value;
+ }
+ }
+
+ ImmutableArray typeReferences;
+ public ImmutableArray TypeReferences {
+ get {
+ var value = typeReferences;
+ if (value.IsDefault)
+ {
+ value = Metadata.TypeReferences
+ .Select(r => new TypeReferenceMetadata(Metadata, r))
+ .Where(r => r.ResolutionScope == Handle)
+ .OrderBy(r => r.Namespace)
+ .ThenBy(r => r.Name)
+ .ToImmutableArray();
+ typeReferences = value;
+ }
+ return value;
+ }
+ }
+
+ ImmutableArray exportedTypes;
+ public ImmutableArray ExportedTypes {
+ get {
+ var value = exportedTypes;
+ if (value.IsDefault)
+ {
+ value = Metadata.ExportedTypes
+ .Select(r => new ExportedTypeMetadata(Metadata, r))
+ .Where(r => r.Implementation == Handle)
+ .OrderBy(r => r.Namespace)
+ .ThenBy(r => r.Name)
+ .ToImmutableArray();
+ exportedTypes = value;
+ }
+ return value;
+ }
+ }
+
+ public ModuleReferenceMetadata(MetadataReader metadata, ModuleReferenceHandle handle)
+ {
+ if (metadata == null)
+ throw new ArgumentNullException(nameof(metadata));
+ if (handle.IsNil)
+ throw new ArgumentNullException(nameof(handle));
+ Metadata = metadata;
+ Handle = handle;
+ entry = metadata.GetModuleReference(handle);
+ }
+
+ public ModuleReferenceMetadata(PEFile module, ModuleReferenceHandle handle)
+ {
+ if (module == null)
+ throw new ArgumentNullException(nameof(module));
+ if (handle.IsNil)
+ throw new ArgumentNullException(nameof(handle));
+ Metadata = module.Metadata;
+ Handle = handle;
+ entry = Metadata.GetModuleReference(handle);
+ }
+
+ public override string ToString()
+ {
+ return Name;
+ }
+ }
+#endif
+}
diff --git a/ICSharpCode.Decompiler/Metadata/PEFile.cs b/ICSharpCode.Decompiler/Metadata/PEFile.cs
index 827940767..c180de179 100644
--- a/ICSharpCode.Decompiler/Metadata/PEFile.cs
+++ b/ICSharpCode.Decompiler/Metadata/PEFile.cs
@@ -177,6 +177,22 @@ namespace ICSharpCode.Decompiler.Metadata
}
}
+ ImmutableArray moduleReferences;
+ public ImmutableArray ModuleReferences {
+ get {
+ var value = moduleReferences;
+ if (value.IsDefault)
+ {
+ value = Metadata.GetModuleReferences()
+ .Select(m => new ModuleReferenceMetadata(this, m))
+ .ToImmutableArray();
+
+ moduleReferences = value;
+ }
+ return value;
+ }
+ }
+
public ImmutableArray Resources => GetResources().ToImmutableArray();
IEnumerable GetResources()
diff --git a/ILSpy/TreeNodes/ModuleReferenceTreeNode.cs b/ILSpy/TreeNodes/ModuleReferenceTreeNode.cs
index b800e5591..c0c37654a 100644
--- a/ILSpy/TreeNodes/ModuleReferenceTreeNode.cs
+++ b/ILSpy/TreeNodes/ModuleReferenceTreeNode.cs
@@ -17,9 +17,13 @@
// DEALINGS IN THE SOFTWARE.
using System;
+using System.Linq;
using System.Reflection.Metadata;
+using System.Reflection.Metadata.Ecma335;
using ICSharpCode.Decompiler;
+using ICSharpCode.Decompiler.Metadata;
+using ICSharpCode.ILSpy.Metadata;
namespace ICSharpCode.ILSpy.TreeNodes
{
@@ -28,6 +32,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
///
sealed class ModuleReferenceTreeNode : ILSpyTreeNode
{
+ readonly PEFile module;
readonly AssemblyTreeNode parentAssembly;
readonly MetadataReader metadata;
readonly ModuleReferenceHandle handle;
@@ -37,20 +42,21 @@ namespace ICSharpCode.ILSpy.TreeNodes
readonly string moduleName;
readonly bool containsMetadata;
- public ModuleReferenceTreeNode(AssemblyTreeNode parentAssembly, ModuleReferenceHandle r, MetadataReader module)
+ public ModuleReferenceTreeNode(AssemblyTreeNode parentAssembly, ModuleReferenceHandle r, PEFile module)
{
this.parentAssembly = parentAssembly ?? throw new ArgumentNullException(nameof(parentAssembly));
if (r.IsNil)
throw new ArgumentNullException(nameof(r));
- this.metadata = module;
this.handle = r;
- this.reference = module.GetModuleReference(r);
+ this.module = module ?? throw new ArgumentNullException(nameof(module));
+ this.metadata = module.Metadata;
+ this.reference = module.Metadata.GetModuleReference(r);
this.moduleName = Language.EscapeName(metadata.GetString(reference.Name));
- foreach (var h in module.AssemblyFiles)
+ foreach (var h in metadata.AssemblyFiles)
{
- var file = module.GetAssemblyFile(h);
- if (module.StringComparer.Equals(file.Name, moduleName))
+ var file = metadata.GetAssemblyFile(h);
+ if (metadata.StringComparer.Equals(file.Name, moduleName))
{
this.file = file;
this.fileHandle = h;
diff --git a/ILSpy/TreeNodes/ReferenceFolderTreeNode.cs b/ILSpy/TreeNodes/ReferenceFolderTreeNode.cs
index adb72732c..9d8452d4a 100644
--- a/ILSpy/TreeNodes/ReferenceFolderTreeNode.cs
+++ b/ILSpy/TreeNodes/ReferenceFolderTreeNode.cs
@@ -51,7 +51,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
foreach (var r in module.AssemblyReferences.OrderBy(r => r.Name))
this.Children.Add(new AssemblyReferenceTreeNode(module, r, parentAssembly));
foreach (var r in metadata.GetModuleReferences().OrderBy(r => metadata.GetString(metadata.GetModuleReference(r).Name)))
- this.Children.Add(new ModuleReferenceTreeNode(parentAssembly, r, metadata));
+ this.Children.Add(new ModuleReferenceTreeNode(parentAssembly, r, module));
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)