API
This article provides an overview of the main API for the @wroud/di package. It explains the key classes and functions available for managing dependency injection.
ServiceContainerBuilder
The ServiceContainerBuilder class is used to register services and build the service provider.
Methods
addSingleton<T>(service: SingleServiceImplementation<T>): this- Registers a singleton service to itself.
addSingleton<T>(service: SingleServiceType<T>, factory: IServiceFactory<T>): this- Registers a singleton service with a factory implementation.
addSingleton<T>(service: SingleServiceType<T>, constructor: IServiceConstructor<T>): this- Registers a singleton service with a constructor implementation.
addSingleton<T>(service: SingleServiceType<T>, implementation: T): this- Registers a singleton service with an instance as implementation.
addSingleton<T>(service: SingleServiceType<T>, resolver: IServiceImplementationResolver<T>): this- Registers a singleton service with a service resolver as implementation.
addTransient<T>(service: SingleServiceImplementation<T>): this- Registers a transient service.
addTransient<T>(service: SingleServiceType<T>, factory: IServiceFactory<T>): this- Registers a transient service with a factory implementation.
addTransient<T>(service: SingleServiceType<T>, constructor: IServiceConstructor<T>): this- Registers a transient service with a constructor implementation.
addTransient<T>(service: SingleServiceType<T>, resolver: IServiceImplementationResolver<T>): this- Registers a transient service with an service resolver as implementation.
addScoped<T>(service: SingleServiceImplementation<T>): this- Registers a scoped service.
addScoped<T>(service: SingleServiceType<T>, factory: IServiceFactory<T>): this- Registers a scoped service with a factory implementation.
addScoped<T>(service: SingleServiceType<T>, constructor: IServiceConstructor<T>): this- Registers a scoped service with a constructor implementation.
addScoped<T>(service: SingleServiceType<T>, resolver: IServiceImplementationResolver<T>): this- Registers a scoped service with an service resolver as implementation.
build(): IServiceProvider- Builds and returns the service provider.
Example
import { ServiceContainerBuilder } from "@wroud/di";
import Logger from "./Logger";
import ILoggerService from "./ILoggerService";
const builder = new ServiceContainerBuilder();
builder.addSingleton(Logger);
builder.addSingleton(ILoggerService, Logger);
builder.addSingleton(ILoggerService, () => new Logger());
const provider = builder.build();IServiceProvider
The IServiceProvider interface is used to resolve services.
Methods
getService<T>(service: ServiceType<T>): T- Resolves and returns an instance of the requested service.
getServices<T>(service: ServiceType<T>): T[]- Resolves and returns all instances of the requested service.
getServiceAsync<T>(service: ServiceType<T>): Promise<T>- Resolves and returns an instance of the requested service asynchronously.
getServicesAsync<T>(service: ServiceType<T>): Promise<T[]>- Resolves and returns all instances of the requested service asynchronously.
createScope(): IAsyncServiceScope- Creates and returns a new scope with
IServiceProviderandSymbol.disposefunction.
- Creates and returns a new scope with
createAsyncScope(): IServiceScope- Creates and returns a new scope with
IServiceProviderandSymbol.asyncDisposefunction.
- Creates and returns a new scope with
[Symbol.dispose](): void- Disposes of the
IServiceProviderand any services that require disposal.
- Disposes of the
[Symbol.asyncDispose](): Promise<void>- Disposes of the
IServiceProviderand any services that require disposal.
- Disposes of the
Example
import Logger from "./Logger";
const logger = provider.getService(Logger);
logger.log("Hello world!");
const loggers = provider.getServices(Logger);
loggers.forEach((logger) => logger.log("Hello from multiple loggers!"));
const scope = provider.createScope();
const scopedLogger = scope.serviceProvider.getService(Logger);
scopedLogger.log("Scoped Hello world!");
provider.dispose();lazy
The lazy function allows you to define services that are loaded asynchronously, enabling lazy-loading within your application. This function wraps the dynamic import statement, ensuring that the service is only loaded when first requested.
Usage
To use the lazy function, wrap your service's dynamic import statement within lazy, and register the service as usual.
Example
import { lazy, ServiceContainerBuilder } from "@wroud/di";
import { IAdministration } from "./Administration/IAdministration";
const builder = new ServiceContainerBuilder();
builder.addSingleton(
IAdministration,
lazy(() =>
import("./Administration/Administration").then((m) => m.Administration),
),
);In this example, the IAdministration service is registered to be loaded asynchronously. The service will only be resolved when accessed using the getServiceAsync or getServicesAsync methods of IServiceProvider.
ServiceRegistry
The ServiceRegistry class allows registering service metadata such as dependencies.
Methods
register(service: Class, metadata: IServiceMetadata)- Registers a service with its metadata.
Example
import { all, optional, ServiceRegistry } from "@wroud/di";
import Logger from "./Logger";
import Formatter from "./Formatter";
import LoggerNode from "./LoggerNode";
import LoggerBrowser from "./LoggerBrowser";
ServiceRegistry.register(Logger, {
name: "Logger",
dependencies: [all(Formatter), LoggerNode, optional(LoggerBrowser)],
});- Injects an array of
Formatterimplementations as the first argument of a constructor,LoggerNodeimplementation as the second argument and implementation resolver ofLoggerBrowseras a third argument.
createService
The createService function creates a token that can be used to resolve services.
Example
const ILoggerService = createService<ILoggerService>("ILoggerService");injectable
The injectable decorator marks a class as injectable and registers its dependencies.
Overloads
@injectable()@injectable(() => [Service])- Injects the
Serviceimplementation as the first argument of a constructor.
- Injects the
@injectable(() => [Service, [Service2]])- Injects the
Serviceimplementation as the first argument of a constructor and an array ofService2implementations as the second argument of a constructor.
- Injects the
@injectable(({ single, all, optional }) => [single(Service), all(Service2), optional(Service3)])- Injects the
Serviceimplementation as the first argument of a constructor, an array ofService2implementations as the second argument of a constructor and theService3implementation resolver as the third argument of a constructor.
- Injects the
Example
import { injectable, type IOptionalService } from "@wroud/di";
@injectable()
class Logger {
log(message: string) {
console.log(message);
}
}
@injectable(() => [Logger])
class Service {
constructor(private readonly logger: Logger) {}
action() {
this.logger.log("Action executed");
}
}
@injectable(() => [Logger, [Service]])
class AnotherService {
constructor(
private readonly logger: Logger,
private readonly services: Service[],
) {}
anotherAction() {
this.services.forEach((service) => service.action());
this.logger.log("Another action executed");
}
}
@injectable(({ all, optional }) => [
Logger,
all(Service),
optional(NodeLogger),
])
class AnotherService {
constructor(
private readonly logger: Logger,
private readonly services: Service[],
private readonly nodeLogger: IOptionalService<NodeLogger>,
) {}
anotherAction() {
this.services.forEach((service) => service.action());
this.logger.log("Another action executed");
}
yetOneAnotherAction() {
const nodeLogger = this.nodeLogger.resolve();
nodeLogger.log("Yet One Another action executed");
}
}This overview provides a quick reference to the main classes and functions in the @wroud/di package. For more detailed information, refer to the full documentation.