ILSpy .NET Assembly Browser and Decompiler
repository·master·Indexed 12 days ago
https://github.com/icsharpcode/ilspyA .NET assembly browser and decompiler featuring ilspycmd for command-line automation, a PowerShell module for programmatic interaction, and a slot-based C# Abstract Syntax Tree (AST) generated via Roslyn source generators.
What's inside ILSpy
- ICSharpCode.ILSpyX is the core cross-platform implementation of ILSpy. It is designed to be decoupled from specific user interfaces, allowing developers to reuse the decompiler logic to build alternative frontends (such as CLI tools, web interfaces, or custom IDE integrations) more easily.
Generate an interactive HTML diagrammer
masterYou can generate an interactive HTML diagrammer app from selected types in the target assembly. By default, it is saved to the
--outputdiror in adiagrammerfolder next to the assembly.Filtering Types
Use regular expressions to control which types are included or excluded from the diagram:
--generate-diagrammer-include <regex>: Whitelist types matching thisType.FullNamepattern.--generate-diagrammer-exclude <regex>: Blacklist types matching thisType.FullNamepattern.--generate-diagrammer-report-excluded: Outputs a report of types that were excluded (either by default, by explicit exclusion, or by implicit inclusion rules) to help debug your regex.
Documentation and Namespaces
--generate-diagrammer-docs <path|uri>: Provide a path orfile://URI to an XML file containing documentation comments to annotate the diagrams.--generate-diagrammer-strip-namespaces <names>: Provide space-separated namespace names to remove from XML documentation comments for brevity (e.g., removeSystem.CollectionsbeforeSystem).
# Generate a HTML diagrammer containing all type info into a folder next to the input assembly ilspycmd sample.dll --generate-diagrammer # Generate a HTML diagrammer with filtered type info ilspycmd sample.dll --generate-diagrammer -o c:\diagrammer --generate-diagrammer-include LightJson\..+ --generate-diagrammer-exclude LightJson\.Serialization\..+Access AST nodes via Slots and Kinds
masterNodes can be queried using Per-node slots (specific to a type, e.g.,
BinaryOperatorExpression.LeftSlot) or Canonical kinds (shared across the AST, found in theSlotsclass).Canonical kinds are matched by reference identity. You can use them for typed access or polymorphic checks:
// Typed access (T is inferred from the Slots constant) node.GetChild(Slots.Left) // Collection access node.GetChildren(Slots.Parameter) // Polymorphic check: "Is this node in an Initializer-kind slot?" node.Slot.Kind == Slots.InitializerHow ILSpy plugins work
masterILSpy uses the Managed Extensibility Framework (MEF) for its plugin architecture. To implement a plugin, you must export specific types for designated extension points.
Deployment Requirements:
- Plugins must be placed in the same directory as
ILSpy.exe. - Plugin assemblies must follow the naming convention
*.Plugin.dll.
Development Setup: To develop a plugin, your project must include references to:
ILSpy.exeSystem.Composition.AttributedModel- Other libraries shipped with ILSpy (depending on your plugin's specific functionality).
- Plugins must be placed in the same directory as
Understand ILAst Pattern Matching instructions
masterIn the ILAst representation, certain IL instructions are classified as "patterns". These instructions are used to represent C# pattern matching logic (like
isexpressions).Key characteristics of pattern instructions (
match.*):TestedOperand: Specifies the operand being matched against the pattern.Variable: Stores the value of theTestedOperand(potentially converted to the matched type).- If used outside the
match.*node, it corresponds to a C#single_variable_designation. - Otherwise, it is a temporary variable with
VariableKind.PatternVar.
- If used outside the
- Evaluation Result: The instruction evaluates to
StackType.I4:0if the pattern matched,1otherwise.
Nested patterns in instructions with a
nestedPatternsbody must satisfy the following:- Each nested pattern must return
truewhen passed toIsPattern(). - The
testedOperandof a nested pattern must be a member (field, property, ordeconstruction.result) of the parent pattern'sVariable. - Exception: For
match.andandmatch.orinstructions, thetestedOperandmust be exactly theVariableof the parent pattern.
How the Mermaid Diagrammer works
masterThe Mermaid Diagrammer generates Mermaid class diagrams from assembly type information through a three-step process:
- Extraction: ILSpy side-loads the source assembly and all its dependencies to extract type information.
- Serialization: The extracted info is structured into a JSON model optimized for HTML rendering. This model combines Mermaid class diagram syntax with metadata regarding relations, inheritance, and documentation comments.
- Assembly & Rendering: The JSON data is injected into a
template.htmlfile. The HTML diagrammer app then re-assembles this data based on user-selected types and rendering options to generate Mermaid class diagrams.
Key Implementation Detail: The JSON type info is baked directly into the
template.htmlfile (alongsidescript.js). This allows the diagrammer to function locally from a file system without a web server, bypassing CORS restrictions while still being able to import the Mermaid module from a CDN.Understand the `ImageListStreamer` on-disk format
masterThe
ImageListStreamerformat is a three-layer nested structure used to serialize WinFormsImageListdata. When implementing or debugging a decoder (likeImageListDecoder.cs), you must process the data in this specific order:- Layer 1: NRBF Envelope — A .NET Remoting Binary Format (NRBF) payload containing a
System.Windows.Forms.ImageListStreamerclass record with aDatabyte array member. - Layer 2:
MSFtRLE Wrapper — An optional Run-Length Encoding (RLE) layer. If the data starts with the magic bytesMSFt(0x4D 0x53 0x46 0x74), it must be decompressed. - Layer 3:
ILHEAD+ DIBs — The raw Win32ImageList_Writestream, consisting of anILHEADstructure followed by color and (optionally) mask Device Independent Bitmaps (DIBs).
- Layer 1: NRBF Envelope — A .NET Remoting Binary Format (NRBF) payload containing a
How the C# AST and its source generator work
masterThe C# Abstract Syntax Tree (AST) is composed of slot-based tree nodes. Instead of manual implementation, most mechanical code—including visitor plumbing, structural pattern matching, child-index APIs, constructors, and slot metadata—is automatically generated by a Roslyn source generator (
DecompilerSyntaxTreeGenerator.cs).To define a node, you declare a
partialclass and use attributes to define its structure. The generator then fills in the remaining implementation details.[DecompilerAstNode] public sealed partial class BinaryOperatorExpression : Expression { [Slot("Left")] public partial Expression? Left { get; set; } // a child slot (optional: nullable) public BinaryOperatorType Operator { get; set; } // a scalar -- a plain auto-property [Slot("Right")] public partial Expression? Right { get; set; } // another child slot }Optimize diagrammer scope and performance
masterLarge assemblies can lead to long build times, massive file sizes, and Mermaid rendering failures if the type selection is too large. To manage this:
- Analyze first: Use the ILSpy GUI to identify specific subdomains worth diagramming.
- Limit scope: Use
--generate-diagrammer-includeand--generate-diagrammer-excludeto restrict the diagrammer to specific namespaces or patterns. - Split diagrammers: Instead of one massive diagrammer, generate multiple smaller ones for different subdomains.
Understand ILSpy event trace providers
masterILSpy emits performance trace events through two distinct
EventSourceproviders. Tracing is disabled by default and only incurs performance costs when a collection session is actively attached. Events are emitted as Start/Stop pairs, allowing trace viewers to calculate durations and nesting levels based on timestamps.Available Providers
ICSharpCode.Decompiler: Instruments the decompilation pipeline, including per-type/per-member decompilation, type system initialization, assembly resolution, whole-project decompilation, and per-transform timing.ICSharpCode.ILSpyX: Instruments frontend support, including assembly loading, reference resolution, search, analyzers, bundle/zip extraction, and PDB loading.
Decompress the Layer 2 `MSFt` RLE wrapper
masterThe second layer uses a specific Run-Length Encoding (RLE) format.
Magic Bytes: The layer is identified by the 4-byte header
MSFt(0x4D 0x53 0x46 0x74). If these bytes are missing, treat the buffer as uncompressed and skip to Layer 3.RLE Algorithm:
- The format consists of
(uint8 count, uint8 value)pairs. count(1..255) is the number of times thevaluerepeats.- There is no end marker; the length is determined by the NRBF byte array size.
- Long runs are split into multiple
(0xFF, v)pairs followed by a remainder pair.
// Decoding logic summary while (reader.TryRead(out byte count)) { reader.TryRead(out byte value); writer.TryWriteCount(count, value); }- The format consists of
Develop and test the HTML diagrammer
masterTo edit the HTML, JS, or CSS for the HTML diagrammer, open the
ICSharpCode.ILSpyX/MermaidDiagrammer/htmlfolder in Visual Studio Code. The development workflow relies on VS Code tasks to manage the build pipeline for testing the diagrammer in a development environment.To successfully develop and test, you must follow this sequence of tasks:
- Generate a model: Use the current Debug build of
ilspycmdto generate amodel.json. This file is a prerequisite for task 3. - Transpile styles: Convert
.lessfiles into.cssfiles. These CSS files are tracked by source control and are eventually embedded into ILSpyX. - Generate development diagrammer: Create a testable diagrammer by combining
template.htmlwith themodel.jsongenerated in step 1. - Auto-rebuild: Enable automatic rebuilding of the development diagrammer by running task 2 or task 3 whenever their respective source files change.
- Generate a model: Use the current Debug build of