Files
TSinjex/src/DIContainer.ts

97 lines
2.6 KiB
TypeScript

import { ImplementsStatic } from './helper/ImplementsStatic';
import { ITSInjex, ITSInjex_ } from './interfaces/IDIContainer';
/**
* Dependency Entry Interface
*/
interface IDependency {
/**
* The dependency itself
*/
dependency: unknown;
/**
* If true, the dependency is deprecated => a warning
* is logged when the dependency is resolved
*/
deprecated?: boolean;
}
/**
* Dependency Injection Container
*/
@ImplementsStatic<ITSInjex_>()
export class DIContainer implements ITSInjex {
private static _instance: DIContainer;
private readonly _dependencies = new Map<string, IDependency>();
/**
* Private constructor to prevent direct instantiation.
*/
private constructor() {}
//#region IDIContainer_
/**
* Retrieves the singleton instance of DependencyRegistry.
* @returns The singleton instance.
*/
public static getInstance(): ITSInjex {
if (this._instance == null) {
this._instance = new DIContainer();
}
return this._instance;
}
//#endregion
//#region IDIContainer
/**
* Register a dependency
* @param identifier The identifier of the dependency
* @param dependency The dependency to register
* @param deprecated If true, the dependency is deprecated => a warning
* is logged when the dependency is resolved
*/
public register<T>(
identifier: string,
dependency: T,
deprecated = false,
): void {
this._dependencies.set(identifier, {
dependency: dependency,
deprecated: deprecated,
});
}
/**
* Resolve a dependency
* @param identifier The identifier of the dependency
* @param necessary If true, throws an error if the dependency is not found
* @returns The resolved dependency or undefined if the dependency is not found (if necessary is false)
* @throws Error if the dependency is not found (if necessary is true)
*/
public resolve<T>(identifier: string, necessary = true): T | undefined {
const dependency = this._dependencies.get(identifier);
if (necessary && !dependency) {
throw new Error(`Dependency ${identifier} not found`);
} else if (!dependency) {
return undefined;
}
if (dependency.deprecated) {
// eslint-disable-next-line no-console
console.warn(`Dependency ${identifier} is deprecated`);
// Remove the deprecation warning; it should only be logged once.
dependency.deprecated = false;
}
return dependency.dependency as T;
}
//#endregion
}