Skip to content

Assembly Architecture

Pavel Koneski edited this page Apr 11, 2026 · 1 revision

DLR Assembly Architecture

This note describes the relationship between the three core DLR assemblies in src/core/:

  • Microsoft.Scripting
  • Microsoft.Dynamic
  • Microsoft.Scripting.Metadata

It is intended as a quick orientation guide for contributors working in the DLR subtree and for language implementations such as IronPython that build on top of it.

Dependency Tree

At the project level, the dependency direction is:

Microsoft.Scripting
Microsoft.Scripting.Metadata -> Microsoft.Scripting
Microsoft.Dynamic -> Microsoft.Scripting
Microsoft.Dynamic -> Microsoft.Scripting.Metadata   (when FEATURE_METADATA_READER is enabled)

In practice, FEATURE_METADATA_READER is enabled by the DLR build for the current target frameworks, so Microsoft.Dynamic normally consumes Microsoft.Scripting.Metadata.

Layering

The assemblies form a simple stack:

graph TD
    A[Language implementations, including IronPython] --> B[Microsoft.Dynamic]
    B --> C[Microsoft.Scripting.Metadata]
    B --> D[Microsoft.Scripting]
    A --> D
    C --> D
Loading

The intended separation is:

  • Microsoft.Scripting provides the base hosting and runtime contracts.
  • Microsoft.Dynamic provides the heavier execution, code generation, interpreter, and interop machinery used by dynamic languages.
  • Microsoft.Scripting.Metadata provides low-level PE and CLR metadata reading used for specific reflection-oriented fast paths.

Microsoft.Scripting

Microsoft.Scripting is the foundational DLR assembly. It defines the public concepts that hosts and language runtimes use to communicate.

Primary purpose

  • Define the hosting API surface.
  • Define source-code, compilation, scope, and runtime abstractions.
  • Provide shared runtime services that language implementations extend.
  • Provide general utility code used across the DLR.

Main contents

Key areas in the project are:

  • Hosting/: host-facing APIs such as ScriptRuntime, ScriptEngine, ScriptSource, ScriptScope, CompiledCode, and related setup/configuration types.
  • Runtime/: core runtime abstractions such as LanguageContext, ScriptDomainManager, Scope, ScriptCode, DynamicOperations, and tokenizer/parser service hooks.
  • Root-level source unit and diagnostics types such as SourceUnit, SourceSpan, SourceLocation, ErrorSink, SyntaxErrorException, and compiler option types.
  • Utils/: shared utility helpers used across the DLR.

What belongs here

Code belongs in Microsoft.Scripting when it defines a cross-language abstraction or a host/runtime API surface that should exist independently of a specific execution strategy.

Typical examples:

  • host configuration and runtime startup
  • source text and error reporting
  • scope and engine abstractions
  • language service extension points

Microsoft.Dynamic

Microsoft.Dynamic sits above Microsoft.Scripting and contains much of the implementation machinery dynamic languages actually rely on at runtime.

Although the project name is Microsoft.Dynamic, many of its namespaces are still under Microsoft.Scripting.*. This is historical DLR structure rather than a layering violation.

Primary purpose

  • Implement execution infrastructure for dynamic languages.
  • Provide code-generation and interpreter support.
  • Extend expression tree support with DLR-specific nodes and helpers.
  • Provide interop, debugging, and reflection helpers used by language implementations.

Main contents

Key areas in the project are:

  • Ast/: DLR expression-tree extensions and builders.
  • Interpreter/: the light interpreter, interpreted frames, instruction set, and light lambda support.
  • Generation/: IL generation, dynamic assembly generation, snippets, delegate helpers, and related emit infrastructure.
  • ComInterop/: COM binding and interop helpers.
  • Debugging/: runtime debugging support.
  • Runtime/: a smaller set of runtime-adjacent implementation helpers.
  • Utils/: reflection and collection helpers, including metadata-assisted reflection fast paths.
  • Xaml/: XAML-related support for dynamic objects.

What belongs here

Code belongs in Microsoft.Dynamic when it is lower-level implementation machinery rather than a base host/runtime contract.

Typical examples:

  • interpreter execution engine
  • dynamic IL or assembly emission
  • expression rewriting or custom AST nodes
  • COM interop support
  • reflection helpers with performance-oriented implementation details

Microsoft.Scripting.Metadata

Microsoft.Scripting.Metadata is a focused support assembly for reading CLI metadata directly from PE files and loaded modules.

Primary purpose

  • Parse PE and CLR metadata structures directly.
  • Expose metadata table readers and helpers.
  • Support reflection-oriented optimizations without relying exclusively on higher-level reflection APIs.

Main contents

Key areas in the project are:

  • PE file structures and readers
  • metadata table enumerators and table implementations
  • memory-mapped and block-based readers
  • helpers for converting metadata records into CLR-facing concepts such as AssemblyName
  • services that expose targeted metadata queries, such as visible extension-method discovery

What belongs here

Code belongs in Microsoft.Scripting.Metadata when it is specifically about reading or interpreting CLI metadata. It should stay narrowly focused; general reflection helpers belong elsewhere.

Why Microsoft.Dynamic Uses Metadata

The clearest current dependency is in reflection utilities. Microsoft.Dynamic uses Microsoft.Scripting.Metadata to provide a fast path for discovering visible extension methods in assemblies when metadata-reader support is available and trusted.

That keeps metadata parsing isolated in a dedicated assembly while allowing Microsoft.Dynamic to use it for performance-sensitive reflection tasks.

Practical Guidance For Contributors

When deciding where to place new code:

  • prefer Microsoft.Scripting for stable, cross-language abstractions and host-facing APIs;
  • prefer Microsoft.Dynamic for implementation details, execution machinery, and performance-oriented helpers;
  • prefer Microsoft.Scripting.Metadata only for narrowly scoped metadata-reader functionality;
  • avoid pulling metadata-reading logic directly into Microsoft.Dynamic unless it truly belongs in the dedicated metadata layer.

Keeping this layering intact makes the DLR easier to reason about and reduces accidental coupling between public hosting abstractions and low-level implementation details.