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 an 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
IServiceProvider
andSymbol.dispose
function.
- Creates and returns a new scope with
createAsyncScope(): IServiceScope
- Creates and returns a new scope with
IServiceProvider
andSymbol.asyncDispose
function.
- Creates and returns a new scope with
[Symbol.dispose](): void
- Disposes of the
IServiceProvider
and any services that require disposal.
- Disposes of the
[Symbol.asyncDispose](): Promise<void>
- Disposes of the
IServiceProvider
and 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 { single, 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), single(LoggerNode), optional(LoggerBrowser)],
});
- Injects an array of
Formatter
implementations as the first argument of a constructor,LoggerNode
implementation as the second argument and implementation resolver ofLoggerBrowser
as 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
Service
implementation as the first argument of a constructor.
- Injects the
@injectable(() => [Service, [Service2]])
- Injects the
Service
implementation as the first argument of a constructor and an array ofService2
implementations as the second argument of a constructor.
- Injects the
@injectable(({ single, all, optional }) => [single(Service), all(Service2), optional(Service3)])
- Injects the
Service
implementation as the first argument of a constructor, an array ofService2
implementations as the second argument of a constructor and theService3
implementation 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(({ single, all, optional }) => [
single(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.