What are Services?
Services are singleton instances that:- Provide specific functionality (editor management, lifecycle, configuration, etc.)
- Use dependency injection for loose coupling
- Follow a clear interface-based design
- Are instantiated on-demand or at specific lifecycle phases
All services in VS Code follow the pattern: Define an interface starting with
I, then implement it in a concrete class.Creating a Service
1. Define the Service Interface
First, create a service decorator and interface:The
_serviceBrand property is a type-only brand that ensures type safety in TypeScript. It’s never actually implemented.2. Implement the Service
Create the concrete implementation:3. Register the Service
Register the service as a singleton:Instantiation Types
Instantiation Types
InstantiationType.Delayed (Recommended)
- Service is created only when first requested
- Reduces startup time
- Most services should use this
- Service is created immediately at startup
- Only use for critical services that must exist early
- Examples: lifecycle service, log service
Common Workbench Services
VS Code provides many built-in services. Here are the most commonly used:Editor Service
Manages editor instances and their lifecycle:Lifecycle Service
Manages application lifecycle phases and shutdown:View Descriptor Service
Manages views and view containers:Configuration Service
Accesses and modifies user/workspace settings:Storage Service
Persists data across sessions:Service Location
Services are organized by scope:- Platform Services
- Workbench Services
Dependency Injection Patterns
Constructor Injection
The most common pattern - inject dependencies through the constructor:Accessor Injection
For command handlers and contributions:Manual Instantiation
For creating instances manually:Best Practices
Service Design Guidelines
Service Design Guidelines
- Single Responsibility: Each service should have one clear purpose
- Interface First: Always define the interface before implementation
- Immutable APIs: Service methods should not modify internal state unexpectedly
- Event-Driven: Use events (
Emitter) for state changes - Lazy Initialization: Use
InstantiationType.Delayedunless eager loading is required - Proper Disposal: Extend
Disposableand register disposables with_register() - Avoid Circular Dependencies: Design services to avoid circular references
Testing Services
Create mock services for testing:Next Steps
Workbench Contributions
Learn how to register contributions that use services
Extension API
Understand how services relate to the extension API