##// END OF EJS Templates
Added childContainer service to container services, ServiceContaier is destroyable, fixed browser Uuid version
Added childContainer service to container services, ServiceContaier is destroyable, fixed browser Uuid version

File last commit:

r144:f97a113c3209 v1.4.0-rc4 default
r146:f3f5c56d3b3e v1.4.0-rc5 default
Show More
LifetimeManager.ts
197 lines | 5.4 KiB | video/mp2t | TypeScriptLexer
/ src / main / ts / di / LifetimeManager.ts
import { IDestroyable, MapOf } from "../interfaces";
import { argumentNotNull, isDestroyable, argumentNotEmptyString } from "../safe";
import { ILifetime, ServiceContainer } from "./interfaces";
import { ActivationContext } from "./ActivationContext";
function safeCall(item: () => void) {
try {
item();
} catch {
// silence!
}
}
const emptyLifetime: ILifetime = Object.freeze({
has() {
return false;
},
initialize() {
},
get() {
throw new Error("The specified item isn't registered with this lifetime manager");
},
store() {
// does nothing
}
});
const unknownLifetime: ILifetime = Object.freeze({
has() {
return false;
},
initialize() {
throw new Error("Can't call initialize on the unknown lifetime object");
},
get() {
throw new Error("The lifetime object isn't initialized");
},
store() {
throw new Error("Can't store a value in the unknown lifetime object");
}
});
let nextId = 0;
const singletons: any = {};
export class LifetimeManager implements IDestroyable {
private _cleanup: (() => void)[] = [];
private _cache: MapOf<any> = {};
private _destroyed = false;
private _pending: MapOf<boolean> = {};
create(): ILifetime {
const self = this;
const id = ++nextId;
return {
has() {
return (id in self._cache);
},
get() {
const t = self._cache[id];
if (t === undefined)
throw new Error(`The item with with the key ${id} isn't found`);
return t;
},
initialize() {
if (self._pending[id])
throw Error(`Cyclic reference detected: the item with the key ${id} is already activating.`);
self._pending[id] = true;
},
store(item: any, cleanup?: (item: any) => void) {
argumentNotNull(id, "id");
argumentNotNull(item, "item");
if (this.has())
throw new Error(`The item with with the key ${id} already registered with this lifetime manager`);
delete self._pending[id];
self._cache[id] = item;
if (self._destroyed)
throw new Error("Lifetime manager is destroyed");
if (cleanup) {
self._cleanup.push(() => cleanup(item));
} else if (isDestroyable(item)) {
self._cleanup.push(() => item.destroy());
}
}
};
}
destroy() {
if (!this._destroyed) {
this._destroyed = true;
this._cleanup.forEach(safeCall);
this._cleanup.length = 0;
}
}
static empty(): ILifetime {
return emptyLifetime;
}
static hierarchyLifetime(): ILifetime {
let _lifetime = unknownLifetime;
return {
initialize(context: ActivationContext<any>) {
if (_lifetime !== unknownLifetime)
throw new Error("Cyclic reference activation detected");
_lifetime = context.getContainer().getLifetimeManager().create();
},
get() {
return _lifetime.get();
},
has() {
return _lifetime.has();
},
store(item: any, cleanup?: (item: any) => void) {
return _lifetime.store(item, cleanup);
}
};
}
static contextLifetime(): ILifetime {
let _lifetime = unknownLifetime;
return {
initialize(context: ActivationContext<any>) {
if (_lifetime !== unknownLifetime)
throw new Error("Cyclic reference detected");
_lifetime = context.createLifetime();
},
get() {
return _lifetime.get();
},
has() {
return _lifetime.has();
},
store(item: any) {
_lifetime.store(item);
}
};
}
static singletonLifetime(typeId: string): ILifetime {
argumentNotEmptyString(typeId, "typeId");
let pending = false;
return {
has() {
return typeId in singletons;
},
get() {
if (!this.has())
throw new Error(`The instance ${typeId} doesn't exists`);
return singletons[typeId];
},
initialize() {
if (pending)
throw new Error("Cyclic reference detected");
pending = true;
},
store(item: any) {
singletons[typeId] = item;
pending = false;
}
};
}
static containerLifetime(container: ServiceContainer<any>) {
let _lifetime = unknownLifetime;
return {
initialize(context: ActivationContext<any>) {
if (_lifetime !== unknownLifetime)
throw new Error("Cyclic reference detected");
_lifetime = container.getLifetimeManager().create();
},
get() {
return _lifetime.get();
},
has() {
return _lifetime.has();
},
store(item: any) {
_lifetime.store(item);
}
};
}
}