Files
XCDesktop/remote/src/core/Container.js
2026-03-08 01:34:54 +08:00

78 lines
1.7 KiB
JavaScript

class Container {
constructor() {
this._services = new Map();
this._singletons = new Map();
this._resolving = new Set();
}
register(name, factory, isSingleton = true) {
if (typeof name !== 'string' || name.trim() === '') {
throw new Error('Service name must be a non-empty string');
}
if (typeof factory !== 'function') {
throw new Error('Factory must be a function');
}
if (this._services.has(name)) {
throw new Error(`Service "${name}" is already registered`);
}
this._services.set(name, { factory, isSingleton });
return this;
}
resolve(name) {
if (!this._services.has(name)) {
throw new Error(`Service "${name}" is not registered`);
}
if (this._resolving.has(name)) {
const chain = Array.from(this._resolving).join(' -> ');
throw new Error(
`Circular dependency detected: ${chain} -> ${name}. ` +
`This creates a circular reference that cannot be resolved.`
);
}
const service = this._services.get(name);
if (service.isSingleton && this._singletons.has(name)) {
return this._singletons.get(name);
}
this._resolving.add(name);
try {
const instance = service.factory(this);
if (service.isSingleton) {
this._singletons.set(name, instance);
}
return instance;
} finally {
this._resolving.delete(name);
}
}
has(name) {
return this._services.has(name);
}
unregister(name) {
if (!this._services.has(name)) {
return false;
}
this._services.delete(name);
this._singletons.delete(name);
return true;
}
clear() {
this._services.clear();
this._singletons.clear();
this._resolving.clear();
}
}
module.exports = Container;