Skip to main content
The Instantiation Service is VS Code’s dependency injection (DI) framework. It manages service lifetimes, resolves dependencies automatically, and provides a clean way to access platform services throughout the codebase.

Overview

VS Code uses constructor-based dependency injection with decorators to declare service dependencies. The Instantiation Service creates instances with all their dependencies automatically resolved.

Core Concepts

Service Identifiers

Services are identified by unique ServiceIdentifier tokens created with createDecorator:
Service Brand: The _serviceBrand property is a TypeScript trick that ensures type safety. It’s never actually used at runtime but prevents accidental type mismatches.

Service Implementation

Implement services as classes and declare dependencies using parameter decorators:

Registering Services

Register services using ServiceCollection or SyncDescriptor:

The IInstantiationService Interface

Common Usage Patterns

Use createInstance() to instantiate classes with automatic dependency resolution:
You can also pass additional static arguments:
invokeFunction() lets you access services without creating a class:
This is useful for one-off operations or when you need services in a function rather than a class.
Child services inherit parent services but can override specific ones:
This is commonly used for:
  • Testing (mocking services)
  • Scoped services (window-specific, editor-specific)
  • Isolated contexts

Service Descriptors

SyncDescriptor enables lazy service instantiation:
Benefits of using descriptors:
  • Services are only created when first accessed
  • Reduces startup time
  • Enables cyclic dependency resolution
  • Supports delayed instantiation via proxies

Advanced Features

Cyclic Dependency Detection

The Instantiation Service detects and reports cyclic dependencies:
The error message includes a graph showing the dependency cycle.

Delayed Instantiation

Services can opt into delayed instantiation using proxies:
With delayed instantiation:
  • A proxy is returned immediately
  • The real service is created during idle time or on first property access
  • Event subscriptions work correctly before instantiation
  • Improves startup performance for heavy services

Service Collection

Real-World Example

Here’s how the Editor service is typically structured:

Best Practices

Always use interfaces: Define service interfaces separately from implementations. This enables testing with mock implementations.
One service identifier per service: Each service should have exactly one ServiceIdentifier. Don’t create multiple identifiers for the same service.
Minimize constructor logic: Keep constructor logic minimal. Use initialization methods or lifecycle hooks for complex setup.
Dispose resources: If your service holds resources (subscriptions, file handles), implement IDisposable and clean up in dispose().

Testing with Dependency Injection

The DI system makes testing easy:

See Also