Metadata Inspector
Browse, query, and compare .NET assembly metadata. Standalone command-line tool; no license required to use the inspector itself.
Overview
The Metadata Inspector is a standalone command-line tool for examining .NET assembly metadata. It ships as a separate global tool (WiseOwl.Inspector, command inspector) and requires no Demeanor license to run — installing WiseOwl.Demeanor auto-installs it on first use. It reads any .NET assembly (Framework, Core, .NET 5–10) and lets you explore its types, methods, fields, properties, events, custom attributes, IL code, and all 31 ECMA-335 metadata tables.
Use it to:
- Understand the structure of any .NET assembly
- Verify what an obfuscator preserved or renamed
- Compare assemblies before and after obfuscation
- Audit assemblies for specific attributes, interfaces, or patterns
- Decode custom attribute blobs without writing code
Installation
Installing Demeanor auto-installs the inspector the first time you run demeanor, so inspector is already on your PATH if you followed Getting Started. To install the inspector on its own (no Demeanor required):
dotnet tool install -g WiseOwl.Inspector
Then run:
inspector MyApp.dll
Two Ways to Use It
One-shot mode (CLI flags)
Pass flags to get a specific view and exit:
inspector MyApp.dll --summary
inspector MyApp.dll --table typedef
inspector MyApp.dll --type WeatherForecast
inspector MyApp.dll --query "show public methods returning string"
Interactive mode (REPL)
Launch without flags to enter the interactive prompt. Type queries directly:
inspector MyApp.dll
inspector> summary
inspector> show public methods
inspector> which types implement IDisposable
inspector> describe OrderService
inspector> quit
Query Language
The inspector understands structured English queries. You don't need to memorize command syntax — describe what you want to see. The inspector shows how it interpreted your query before displaying results.
Showing items
| Query | What it does |
summary | Assembly identity, version, and row counts |
show types | List all types |
show methods | List all methods |
show fields | List all fields |
show properties | List all properties |
show events | List all events |
show resources | List embedded resources |
show assembly references | List referenced assemblies |
show custom attributes | List custom attributes |
show interfaces | List interface types |
Filtering by accessibility
| Query | What it does |
show public types | Only public types |
show public methods | Only public methods |
show internal types | Only internal types |
show private methods | Only private methods |
Filtering by signature
| Query | What it does |
show methods returning string | Methods whose return type contains "string" |
show methods returning void | Methods returning void |
show methods that take int | Methods with a parameter type containing "int" |
show static methods | Static methods only |
show virtual methods | Virtual methods only |
show abstract methods | Abstract methods only |
Filtering by owner / location
| Query | What it does |
show methods on Calculator | Methods declared on types matching "Calculator" |
show fields on OrderService | Fields on types matching "OrderService" |
types in namespace MyApp.Models | Types in a specific namespace |
Filtering by type hierarchy
| Query | What it does |
which types implement IDisposable | Types implementing a specific interface |
types that inherit from Exception | Types with a specific base class |
types with attribute Serializable | Types decorated with a specific attribute |
show generic types | Types with generic parameters |
show sealed types | Sealed types |
Counting
| Query | What it does |
how many types | Count of types |
how many methods | Count of methods |
how many fields | Count of fields |
how many properties | Count of properties |
count resources | Count of embedded resources |
Detail views
| Query | What it does |
describe OrderService | Full type detail: base type, interfaces, fields, methods, properties |
show type Calculator | Same as describe |
what is WeatherForecast | Same as describe |
Searching
| Query | What it does |
find Calculator | Search all types, methods, fields, and properties for "Calculator" |
find Dispose | Search across all tables for "Dispose" |
How matching works
All name matching is case-insensitive and uses substring containment by default. show methods on Order matches OrderService, OrderRepository, and ReorderQueue.
Driving the inspector from an AI assistant (optional)
This section is optional. The inspector’s primary interface is the CLI documented above — the REPL and one-shot commands cover every capability, and the structured English query language needs no AI to work.
If you already use an MCP-capable assistant (Claude Code, Claude Desktop, Cursor, Windsurf, Continue.dev, or any other MCP client), the inspector’s opt-in MCP server lets the assistant answer the same questions in conversation on your behalf. The inspector auto-registers with detected MCP clients the first time you install it — nothing to configure, no separate API key. Everything runs locally; no assembly data leaves your machine. Requires your own Claude subscription — not included with Demeanor.
Ask it anything
What should I exclude before obfuscating this assembly?
The assistant inspects serializable types, data-bound properties, reflection usage, and public API surfaces, then recommends exclusions with rationale.
Which types implement IHostedService?
The assistant queries the metadata and lists the matching types with a brief note on how each one is used.
Compare the pre- and post-obfuscation builds — did anything framework-critical get renamed?
The assistant diffs the two assemblies, separates public from internal renames, and flags anything that should have been frozen but wasn’t.
After obfuscation I’m getting a JSON deserialization error. What went wrong?
The assistant reads both builds, identifies which original type was renamed into the conflict, and suggests the fix.
See the conversational walkthrough for an end-to-end conversation where the assistant drives both the inspector and Demeanor’s audit surface in the same session.
One-Shot CLI Options
All options work from the command line for scripting and CI/CD integration.
Display options
| Option | Description |
--summary | Assembly identity and statistics |
--metadata | Display all metadata tables |
--table <name> | Display specific table(s). Repeatable. |
--il | IL disassembly for all methods |
--dependencies | Assembly, type, and member references |
--type <pattern> | Unified type view: fields, methods, properties, events, attributes, MethodImpls |
--diff <other.dll> | Compare against another assembly |
--query <text>, -q | Natural language query (one-shot) |
Filters and formatting
| Option | Description |
--filter <text> | Filter rows by name substring. Supports scoped queries: type=Foo, parent=Bar, sig=string |
--public-only | Restrict output to public symbols |
--json | Output structured JSON for tooling. Forces one-shot mode. |
MCP server (optional)
Metadata Tables
The inspector can display any of the 31 ECMA-335 metadata tables. Use --table <name> in one-shot mode.
Core tables
| Table name | Contents |
typedef | Types defined in this assembly (classes, interfaces, structs, enums, delegates) |
methoddef | Methods defined in this assembly |
fielddef | Fields defined in this assembly |
paramdef | Method parameters with names and default values |
property | Properties with getter/setter references |
event | Events with add/remove/fire accessors |
Reference tables
| Table name | Contents |
typeref | Types referenced from other assemblies |
memberref | Methods and fields referenced from other assemblies |
assemblyref | Referenced assemblies (dependencies) |
typespec | Instantiated generic types (e.g., List<string>) |
methodspec | Instantiated generic methods |
moduleref | Referenced modules (P/Invoke DLLs) |
Relationship tables
| Table name | Contents |
interfaceimpl | Which types implement which interfaces |
nestedclass | Nested type relationships |
methodimpl | Explicit method overrides (.override directives) |
methodsemantics | Property/event accessor mappings |
propertymap | Type → property group mappings |
eventmap | Type → event group mappings |
customattr | Custom attributes on any metadata row |
Generic tables
| Table name | Contents |
genericparam | Generic type/method parameters (T, TKey, etc.) |
Interop and layout tables
| Table name | Contents |
implmap | P/Invoke mappings (unmanaged function imports) |
classlayout | Explicit class size and packing |
fieldlayout | Explicit field offsets |
fieldrva | Fields with data stored at fixed RVAs |
fieldmarshal | Marshalling descriptors for interop |
declsecurity | Declarative security attributes |
standsig | Stand-alone signatures (local variable types) |
Assembly-level tables
| Table name | Contents |
resource | Embedded and linked manifest resources |
exportedtype | Types forwarded to other assemblies |
file | Files in a multi-file assembly |
constant | Compile-time constants (field/param/property defaults) |
Examples
Quick overview of an assembly
inspector MyApp.dll --summary
Compare before and after obfuscation
inspector obfuscated/MyApp.dll --diff original/MyApp.dll
Find all types that implement a specific interface
inspector MyApp.dll -q "which types implement IHostedService"
Audit for specific attributes
inspector MyApp.dll -q "types with attribute JsonSerializable"
Check what an obfuscator preserved
inspector obfuscated/MyApp.dll -q "show public properties"
Explore interactively
inspector MyApp.dll
inspector> summary
Assembly: MyApp
Types: 142
Methods: 891
...
inspector> show types implementing IDisposable
-> Show types implementing IDisposable
public class MyApp.Data.DbContext : System.Object
public class MyApp.Services.HttpClientPool : System.Object
(2 type(s))
inspector> describe DbContext
-> Show details of type DbContext
=== MyApp.Data.DbContext ===
Base: System.Object
Implements: System.IDisposable
Fields (3): ...
Methods (12): ...
inspector> show methods on DbContext
-> Show methods on DbContext
...
inspector> quit
Script-friendly JSON output
inspector MyApp.dll --json --summary
Drive from an AI assistant (optional)
If you already use an MCP-capable assistant, the inspector can be driven conversationally. See Driving the inspector from an AI assistant.
# Ask (if you use an MCP-capable assistant):
# "Show me all public methods that accept a CancellationToken and return Task"
# The assistant queries the inspector and answers in context.
How Query Translation Works
Under the hood, every query (whether typed as English or passed via --table) is converted into a structured InspectQuery object with these fields:
| Field | Purpose | Values |
| Verb | What to do | Show, Find, Count, Detail, List |
| Target | What metadata to query | Types, Methods, Fields, Properties, Events, CustomAttributes, Interfaces, Resources, AssemblyRefs, Summary, All |
| Filters | Which items to include | Zero or more filter predicates (see below) |
| Limit | Max results | Any positive integer, or unlimited |
| Format | Output format | Table, Detail, Json, IL |
Available filter fields
Each filter has a field, an operator, and a value. Not every field applies to every target — the inspector validates compatibility and rejects mismatched combinations.
| Filter field | Applies to | Example |
Name | All targets | Methods named "Dispose" |
FullName | Types, Methods | Types with full name containing "Models" |
Namespace | Types | Types in namespace "MyApp.Data" |
ReturnType | Methods | Methods returning "string" |
ParameterType | Methods | Methods taking "CancellationToken" |
FieldType | Fields | Fields of type "Dictionary" |
PropertyType | Properties | Properties of type "string" |
BaseType | Types | Types inheriting from "Exception" |
Implements | Types | Types implementing "IDisposable" |
HasAttribute | Types, Methods | Types with [Serializable] |
Accessibility | Types, Methods | Public, private, internal, protected |
Owner | Methods, Fields | Methods on type "Calculator" |
IsStatic | Types, Methods, Fields | Static methods |
IsAbstract | Types, Methods | Abstract types or methods |
IsSealed | Types | Sealed types |
IsGeneric | Types | Generic types (with type parameters) |
IsVirtual | Methods | Virtual methods |
Text | All (search mode) | Free-text search across all names |
Filter operators
| Operator | Meaning |
Contains | Value appears anywhere in the field (default, case-insensitive) |
Equals | Exact match (case-insensitive) |
StartsWith | Field starts with the value |
EndsWith | Field ends with the value |
Not | Field does NOT contain the value |
GreaterThan | Numeric comparison (for count fields) |
LessThan | Numeric comparison (for count fields) |
In the CLI, the -> interpretation line shows you how your English was parsed before execution. When driving the inspector from an AI assistant, the assistant constructs queries using these same fields and operators.