Browse Source

Typed leaves for the 6 most-inspected cor tables

Replaces the universal placeholder for Field, MethodDef, Param,
MemberRef, CustomAttribute, and Assembly with their own typed leaves.
Each carries the columns the WPF view shows (RID / Token / Offset / row
data) — the analogous tooltips and click handlers stay deferred to the
Phase-3 navigation work since Phase 1 only renders text. The remaining
25 CorTables continue to land as placeholders until the next pass.

Assisted-by: Claude:claude-opus-4-7:Claude Code
pull/3755/head
Siegfried Pammer 2 months ago
parent
commit
5eee0bc46b
  1. 34
      ILSpy.Tests/Metadata/TypedMetadataTableTreeTests.cs
  2. 82
      ILSpy/Metadata/CorTables/AssemblyTableTreeNode.cs
  3. 81
      ILSpy/Metadata/CorTables/CustomAttributeTableTreeNode.cs
  4. 80
      ILSpy/Metadata/CorTables/FieldTableTreeNode.cs
  5. 79
      ILSpy/Metadata/CorTables/MemberRefTableTreeNode.cs
  6. 90
      ILSpy/Metadata/CorTables/MethodTableTreeNode.cs
  7. 78
      ILSpy/Metadata/CorTables/ParamTableTreeNode.cs
  8. 6
      ILSpy/Metadata/MetadataTablesTreeNode.cs

34
ILSpy.Tests/Metadata/TypedMetadataTableTreeTests.cs

@ -102,6 +102,40 @@ public class TypedMetadataTableTreeTests @@ -102,6 +102,40 @@ public class TypedMetadataTableTreeTests
tab.Text.Should().Contain("Object");
}
[AvaloniaTest]
public async Task FieldAndMethodTables_Decompile_With_Their_Own_Typed_Leaves()
{
// Field / MethodDef are by far the largest tables in any real assembly. The typed
// leaf should report the right table kind, expose a row count, and decompile to a
// table whose first column header is "RID" (the per-table row identifier).
var window = AppComposition.Current.GetExport<MainWindow>();
window.Show();
var vm = (MainWindowViewModel)window.DataContext!;
await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 1);
var coreLibName = typeof(object).Assembly.GetName().Name!;
var assemblyNode = vm.AssemblyTreeModel.FindNode<AssemblyTreeNode>(coreLibName);
assemblyNode.EnsureLazyChildren();
var metadataNode = assemblyNode.Children.OfType<MetadataTreeNode>().Single();
metadataNode.EnsureLazyChildren();
var tablesNode = metadataNode.Children.OfType<MetadataTablesTreeNode>().Single();
tablesNode.EnsureLazyChildren();
tablesNode.Children.OfType<FieldTableTreeNode>().Should().ContainSingle();
tablesNode.Children.OfType<MethodTableTreeNode>().Should().ContainSingle();
tablesNode.Children.OfType<ParamTableTreeNode>().Should().ContainSingle();
tablesNode.Children.OfType<MemberRefTableTreeNode>().Should().ContainSingle();
tablesNode.Children.OfType<CustomAttributeTableTreeNode>().Should().ContainSingle();
tablesNode.Children.OfType<AssemblyTableTreeNode>().Should().ContainSingle();
var methodNode = tablesNode.Children.OfType<MethodTableTreeNode>().Single();
vm.AssemblyTreeModel.SelectNode(methodNode);
var tab = await vm.DockWorkspace.WaitForDecompiledTextAsync();
tab.Text.Should().Contain("MethodDef");
tab.Text.Should().Contain("RID");
}
[AvaloniaTest]
public async Task ModuleTableTreeNode_Decompiles_To_A_Single_Row_Carrying_The_Module_Name()
{

82
ILSpy/Metadata/CorTables/AssemblyTableTreeNode.cs

@ -0,0 +1,82 @@ @@ -0,0 +1,82 @@
// Copyright (c) 2026 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;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using ICSharpCode.Decompiler.Metadata;
namespace ILSpy.Metadata.CorTables
{
/// <summary>
/// View of the Assembly table — at most one row, present only when the metadata file is
/// itself an assembly manifest (vs. a plain .netmodule). Carries the assembly's name,
/// culture, version, hash algorithm, and signing flags.
/// </summary>
public sealed class AssemblyTableTreeNode : MetadataTableTreeNode<AssemblyTableTreeNode.AssemblyEntry>
{
public AssemblyTableTreeNode(MetadataFile metadataFile)
: base(TableIndex.Assembly, metadataFile)
{
}
protected override IReadOnlyList<AssemblyEntry> LoadTable()
=> metadataFile.Metadata.IsAssembly
? [new AssemblyEntry(metadataFile.Metadata, metadataFile.MetadataOffset)]
: [];
public sealed class AssemblyEntry
{
readonly int metadataOffset;
readonly MetadataReader metadata;
readonly AssemblyDefinition assembly;
public int RID => MetadataTokens.GetRowNumber(EntityHandle.AssemblyDefinition);
[ColumnInfo("X8")]
public int Token => MetadataTokens.GetToken(EntityHandle.AssemblyDefinition);
[ColumnInfo("X8")]
public int Offset => metadataOffset
+ metadata.GetTableMetadataOffset(TableIndex.Assembly)
+ metadata.GetTableRowSize(TableIndex.Assembly) * (RID - 1);
[ColumnInfo("X4")]
public AssemblyHashAlgorithm HashAlgorithm => assembly.HashAlgorithm;
[ColumnInfo("X4")]
public AssemblyFlags Flags => assembly.Flags;
public Version Version => assembly.Version;
public string Name => metadata.GetString(assembly.Name);
public string Culture => metadata.GetString(assembly.Culture);
public AssemblyEntry(MetadataReader metadata, int metadataOffset)
{
this.metadata = metadata;
this.metadataOffset = metadataOffset;
assembly = metadata.GetAssemblyDefinition();
}
}
}
}

81
ILSpy/Metadata/CorTables/CustomAttributeTableTreeNode.cs

@ -0,0 +1,81 @@ @@ -0,0 +1,81 @@
// Copyright (c) 2026 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.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using ICSharpCode.Decompiler.Metadata;
namespace ILSpy.Metadata.CorTables
{
/// <summary>
/// View of the CustomAttribute table — every <c>[Attr(...)]</c> annotation attached to
/// every metadata row. Parent is a HasCustomAttribute coded token; Constructor points at
/// the attribute class's ctor (MethodDef or MemberRef); Value blob holds the constructor
/// arguments + named properties as a serialised payload.
/// </summary>
public sealed class CustomAttributeTableTreeNode : MetadataTableTreeNode<CustomAttributeTableTreeNode.CustomAttributeEntry>
{
public CustomAttributeTableTreeNode(MetadataFile metadataFile)
: base(TableIndex.CustomAttribute, metadataFile)
{
}
protected override IReadOnlyList<CustomAttributeEntry> LoadTable()
{
var list = new List<CustomAttributeEntry>();
foreach (var row in metadataFile.Metadata.CustomAttributes)
list.Add(new CustomAttributeEntry(metadataFile, row));
return list;
}
public sealed class CustomAttributeEntry
{
readonly MetadataFile metadataFile;
readonly CustomAttributeHandle handle;
readonly CustomAttribute customAttr;
public int RID => MetadataTokens.GetRowNumber(handle);
[ColumnInfo("X8")]
public int Token => MetadataTokens.GetToken(handle);
[ColumnInfo("X8")]
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);
[ColumnInfo("X8", Kind = ColumnKind.Token)]
public int Constructor => MetadataTokens.GetToken(customAttr.Constructor);
[ColumnInfo("X8", Kind = ColumnKind.HeapOffset)]
public int Value => MetadataTokens.GetHeapOffset(customAttr.Value);
public CustomAttributeEntry(MetadataFile metadataFile, CustomAttributeHandle handle)
{
this.metadataFile = metadataFile;
this.handle = handle;
customAttr = metadataFile.Metadata.GetCustomAttribute(handle);
}
}
}
}

80
ILSpy/Metadata/CorTables/FieldTableTreeNode.cs

@ -0,0 +1,80 @@ @@ -0,0 +1,80 @@
// Copyright (c) 2026 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.Collections.Generic;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using ICSharpCode.Decompiler.Metadata;
namespace ILSpy.Metadata.CorTables
{
/// <summary>
/// View of the Field table — every field defined by the module's types. Each row carries
/// the field's attributes (visibility / static / const / …), name, and the heap offset
/// of its signature blob.
/// </summary>
public sealed class FieldTableTreeNode : MetadataTableTreeNode<FieldTableTreeNode.FieldDefEntry>
{
public FieldTableTreeNode(MetadataFile metadataFile)
: base(TableIndex.Field, metadataFile)
{
}
protected override IReadOnlyList<FieldDefEntry> LoadTable()
{
var list = new List<FieldDefEntry>();
foreach (var row in metadataFile.Metadata.FieldDefinitions)
list.Add(new FieldDefEntry(metadataFile, row));
return list;
}
public sealed class FieldDefEntry
{
readonly MetadataFile metadataFile;
readonly FieldDefinitionHandle handle;
readonly FieldDefinition fieldDef;
public int RID => MetadataTokens.GetRowNumber(handle);
[ColumnInfo("X8")]
public int Token => MetadataTokens.GetToken(handle);
[ColumnInfo("X8")]
public int Offset => metadataFile.MetadataOffset
+ metadataFile.Metadata.GetTableMetadataOffset(TableIndex.Field)
+ metadataFile.Metadata.GetTableRowSize(TableIndex.Field) * (RID - 1);
[ColumnInfo("X8")]
public FieldAttributes Attributes => fieldDef.Attributes;
public string Name => metadataFile.Metadata.GetString(fieldDef.Name);
[ColumnInfo("X8", Kind = ColumnKind.HeapOffset)]
public int Signature => MetadataTokens.GetHeapOffset(fieldDef.Signature);
public FieldDefEntry(MetadataFile metadataFile, FieldDefinitionHandle handle)
{
this.metadataFile = metadataFile;
this.handle = handle;
fieldDef = metadataFile.Metadata.GetFieldDefinition(handle);
}
}
}
}

79
ILSpy/Metadata/CorTables/MemberRefTableTreeNode.cs

@ -0,0 +1,79 @@ @@ -0,0 +1,79 @@
// Copyright (c) 2026 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.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using ICSharpCode.Decompiler.Metadata;
namespace ILSpy.Metadata.CorTables
{
/// <summary>
/// View of the MemberRef table — every external method or field the module references.
/// Parent is a MemberRefParent coded token (TypeRef / ModuleRef / MethodDef / TypeSpec /
/// TypeDef) carrying the owner of the referenced member.
/// </summary>
public sealed class MemberRefTableTreeNode : MetadataTableTreeNode<MemberRefTableTreeNode.MemberRefEntry>
{
public MemberRefTableTreeNode(MetadataFile metadataFile)
: base(TableIndex.MemberRef, metadataFile)
{
}
protected override IReadOnlyList<MemberRefEntry> LoadTable()
{
var list = new List<MemberRefEntry>();
foreach (var row in metadataFile.Metadata.MemberReferences)
list.Add(new MemberRefEntry(metadataFile, row));
return list;
}
public sealed class MemberRefEntry
{
readonly MetadataFile metadataFile;
readonly MemberReferenceHandle handle;
readonly MemberReference memberRef;
public int RID => MetadataTokens.GetRowNumber(handle);
[ColumnInfo("X8")]
public int Token => MetadataTokens.GetToken(handle);
[ColumnInfo("X8")]
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 string Name => metadataFile.Metadata.GetString(memberRef.Name);
[ColumnInfo("X8", Kind = ColumnKind.HeapOffset)]
public int Signature => MetadataTokens.GetHeapOffset(memberRef.Signature);
public MemberRefEntry(MetadataFile metadataFile, MemberReferenceHandle handle)
{
this.metadataFile = metadataFile;
this.handle = handle;
memberRef = metadataFile.Metadata.GetMemberReference(handle);
}
}
}
}

90
ILSpy/Metadata/CorTables/MethodTableTreeNode.cs

@ -0,0 +1,90 @@ @@ -0,0 +1,90 @@
// Copyright (c) 2026 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.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using ICSharpCode.Decompiler.Metadata;
namespace ILSpy.Metadata.CorTables
{
/// <summary>
/// View of the MethodDef table — every method body the module ships. The RVA points
/// into the .text section's IL stream (0 for abstract / interface methods); the
/// ParamList token is the first row in the Param table covering this method's parameters.
/// </summary>
public sealed class MethodTableTreeNode : MetadataTableTreeNode<MethodTableTreeNode.MethodDefEntry>
{
public MethodTableTreeNode(MetadataFile metadataFile)
: base(TableIndex.MethodDef, metadataFile)
{
}
protected override IReadOnlyList<MethodDefEntry> LoadTable()
{
var list = new List<MethodDefEntry>();
foreach (var row in metadataFile.Metadata.MethodDefinitions)
list.Add(new MethodDefEntry(metadataFile, row));
return list;
}
public sealed class MethodDefEntry
{
readonly MetadataFile metadataFile;
readonly MethodDefinitionHandle handle;
readonly MethodDefinition methodDef;
public int RID => MetadataTokens.GetRowNumber(handle);
[ColumnInfo("X8")]
public int Token => MetadataTokens.GetToken(handle);
[ColumnInfo("X8")]
public int Offset => metadataFile.MetadataOffset
+ metadataFile.Metadata.GetTableMetadataOffset(TableIndex.MethodDef)
+ metadataFile.Metadata.GetTableRowSize(TableIndex.MethodDef) * (RID - 1);
[ColumnInfo("X8")]
public MethodAttributes Attributes => methodDef.Attributes;
[ColumnInfo("X8")]
public MethodImplAttributes ImplAttributes => methodDef.ImplAttributes;
[ColumnInfo("X8")]
public int RVA => methodDef.RelativeVirtualAddress;
public string Name => metadataFile.Metadata.GetString(methodDef.Name);
[ColumnInfo("X8", Kind = ColumnKind.HeapOffset)]
public int Signature => MetadataTokens.GetHeapOffset(methodDef.Signature);
[ColumnInfo("X8", Kind = ColumnKind.Token)]
public int ParamList => MetadataTokens.GetToken(methodDef.GetParameters().FirstOrDefault());
public MethodDefEntry(MetadataFile metadataFile, MethodDefinitionHandle handle)
{
this.metadataFile = metadataFile;
this.handle = handle;
methodDef = metadataFile.Metadata.GetMethodDefinition(handle);
}
}
}
}

78
ILSpy/Metadata/CorTables/ParamTableTreeNode.cs

@ -0,0 +1,78 @@ @@ -0,0 +1,78 @@
// Copyright (c) 2026 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.Collections.Generic;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using ICSharpCode.Decompiler.Metadata;
namespace ILSpy.Metadata.CorTables
{
/// <summary>
/// View of the Param table — every formal parameter declared on every method body. Walked
/// by 1-based row index because the metadata reader doesn't expose Param as an IEnumerable.
/// </summary>
public sealed class ParamTableTreeNode : MetadataTableTreeNode<ParamTableTreeNode.ParamEntry>
{
public ParamTableTreeNode(MetadataFile metadataFile)
: base(TableIndex.Param, metadataFile)
{
}
protected override IReadOnlyList<ParamEntry> LoadTable()
{
var list = new List<ParamEntry>();
for (int row = 1; row <= metadataFile.Metadata.GetTableRowCount(TableIndex.Param); row++)
list.Add(new ParamEntry(metadataFile, MetadataTokens.ParameterHandle(row)));
return list;
}
public sealed class ParamEntry
{
readonly MetadataFile metadataFile;
readonly ParameterHandle handle;
readonly Parameter param;
public int RID => MetadataTokens.GetRowNumber(handle);
[ColumnInfo("X8")]
public int Token => MetadataTokens.GetToken(handle);
[ColumnInfo("X8")]
public int Offset => metadataFile.MetadataOffset
+ metadataFile.Metadata.GetTableMetadataOffset(TableIndex.Param)
+ metadataFile.Metadata.GetTableRowSize(TableIndex.Param) * (RID - 1);
[ColumnInfo("X8")]
public ParameterAttributes Attributes => param.Attributes;
public int Sequence => param.SequenceNumber;
public string Name => metadataFile.Metadata.GetString(param.Name);
public ParamEntry(MetadataFile metadataFile, ParameterHandle handle)
{
this.metadataFile = metadataFile;
this.handle = handle;
param = metadataFile.Metadata.GetParameter(handle);
}
}
}
}

6
ILSpy/Metadata/MetadataTablesTreeNode.cs

@ -77,6 +77,12 @@ namespace ILSpy.Metadata @@ -77,6 +77,12 @@ namespace ILSpy.Metadata
TableIndex.Module => new ModuleTableTreeNode(metadataFile),
TableIndex.TypeRef => new TypeRefTableTreeNode(metadataFile),
TableIndex.TypeDef => new TypeDefTableTreeNode(metadataFile),
TableIndex.Field => new FieldTableTreeNode(metadataFile),
TableIndex.MethodDef => new MethodTableTreeNode(metadataFile),
TableIndex.Param => new ParamTableTreeNode(metadataFile),
TableIndex.MemberRef => new MemberRefTableTreeNode(metadataFile),
TableIndex.CustomAttribute => new CustomAttributeTableTreeNode(metadataFile),
TableIndex.Assembly => new AssemblyTableTreeNode(metadataFile),
TableIndex.AssemblyRef => new AssemblyRefTableTreeNode(metadataFile),
_ => new UnsupportedMetadataTableTreeNode(table, metadataFile),
};

Loading…
Cancel
Save