39 lines
1.1 KiB
TypeScript
39 lines
1.1 KiB
TypeScript
export type Provider<T = unknown> = (manager: Manager) => T;
|
|
export interface Identifier<T = unknown> extends Symbol {}
|
|
|
|
export class Manager {
|
|
private providers = new Map<Identifier, Provider>();
|
|
private instances = new Map<Identifier, unknown>();
|
|
private resolving = new Set<Identifier>();
|
|
|
|
register<T>(identifier: Identifier<T>, provider: Provider<T>) {
|
|
if (this.providers.has(identifier)) {
|
|
throw new Error('This identifier is already used');
|
|
}
|
|
|
|
this.providers.set(identifier, provider);
|
|
}
|
|
|
|
inject<T>(identifier: Identifier<T>): T {
|
|
if (!this.providers.has(identifier)) {
|
|
throw new Error('This identifier has not been registred');
|
|
}
|
|
|
|
if (this.instances.has(identifier)) {
|
|
return this.instances.get(identifier) as T;
|
|
}
|
|
|
|
if (this.resolving.has(identifier)) {
|
|
throw new Error('Circular dependency detected');
|
|
}
|
|
|
|
this.resolving.add(identifier);
|
|
const declaration = this.providers.get(identifier) as Provider<T>;
|
|
const instance = declaration(this);
|
|
this.instances.set(identifier, instance);
|
|
this.resolving.delete(identifier);
|
|
|
|
return instance;
|
|
}
|
|
}
|