Learn about VS Code’s dependency injection system and the Instantiation Service
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.
VS Code uses constructor-based dependency injection with decorators to declare service dependencies. The Instantiation Service creates instances with all their dependencies automatically resolved.
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.
Register services using ServiceCollection or SyncDescriptor:
Copy
Ask AI
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';const services = new ServiceCollection();// Register with an instanceservices.set(IMyService, new MyService(...));// Or register with a descriptor (lazy instantiation)services.set(IMyService, new SyncDescriptor(MyService));const instantiationService = new InstantiationService(services);
export interface IInstantiationService { readonly _serviceBrand: undefined; /** * Synchronously creates an instance that is denoted by the descriptor */ createInstance<T>(descriptor: SyncDescriptor0<T>): T; createInstance<Ctor extends new (...args: any[]) => unknown, R extends InstanceType<Ctor>>( ctor: Ctor, ...args: GetLeadingNonServiceArgs<ConstructorParameters<Ctor>> ): R; /** * Calls a function with a service accessor. */ invokeFunction<R, TS extends any[] = []>( fn: (accessor: ServicesAccessor, ...args: TS) => R, ...args: TS ): R; /** * Creates a child of this service which inherits all current services * and adds/overwrites the given services. */ createChild(services: ServiceCollection, store?: DisposableStore): IInstantiationService; /** * Disposes this instantiation service. */ dispose(): void;}
Use createInstance() to instantiate classes with automatic dependency resolution:
Copy
Ask AI
// In a class that receives IInstantiationServiceclass MyController { constructor( @IInstantiationService private readonly instantiationService: IInstantiationService ) {} createWidget(): MyWidget { // MyWidget's dependencies will be automatically injected return this.instantiationService.createInstance(MyWidget); }}
invokeFunction() lets you access services without creating a class:
Copy
Ask AI
this.instantiationService.invokeFunction((accessor) => { const configService = accessor.get(IConfigurationService); const workspaceService = accessor.get(IWorkspaceContextService); const config = configService.getValue('myExtension.setting'); const workspace = workspaceService.getWorkspace(); // Do something with the services...});
This is useful for one-off operations or when you need services in a function rather than a class.
Creating Child Instantiation Services
Child services inherit parent services but can override specific ones:
Copy
Ask AI
const childServices = new ServiceCollection();childServices.set(IMyService, new TestMyService()); // Override for testingconst childInstantiationService = parentInstantiationService.createChild(childServices);// Instances created by child will use TestMyServiceconst instance = childInstantiationService.createInstance(MyComponent);