##// END OF EJS Templates
added provided and configure methods to the fluent container configuration, added applyConfig method to the container
added provided and configure methods to the fluent container configuration, added applyConfig method to the container

File last commit:

r135:03e32ec7c20b ioc ts support
r142:be7edf08a115 v1.4.0-rc3 default
Show More
LifetimeManager.ts
198 lines | 5.5 KiB | video/mp2t | TypeScriptLexer
/ src / main / ts / di / LifetimeManager.ts
import { IDestroyable, MapOf } from "../interfaces";
import { argumentNotNull, isDestroyable, primitive, isNull, argumentNotEmptyString } from "../safe";
import { ILifetime } from "./interfaces";
import { ActivationContext } from "./ActivationContext";
import { Container } from "./Container";
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: { [k in keyof any]: 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: Container<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);
}
};
}
}