Container.ts
71 lines
| 2.3 KiB
| video/mp2t
|
TypeScriptLexer
|
|
r0 | import { ActivationContext } from "./ActivationContext"; | ||
|
|
r5 | import { ContainerBuilder } from "./ContainerBuilder"; | ||
|
|
r15 | import { LifetimeManager, emptySlot } from "./LifetimeManager"; | ||
| import { DescriptorMap, IContainerBuilder, IDestroyable, ILifetimeManager, ILifetimeSlot, ServiceLocator } from "../typings/interfaces"; | ||||
| let nextId = 1; | ||||
|
|
r0 | |||
|
|
r9 | export class Container<S> implements ServiceLocator<S>, IDestroyable { | ||
| private readonly _services: DescriptorMap<S>; | ||||
|
|
r0 | |||
|
|
r15 | private readonly _scope: ILifetimeManager[]; | ||
| private readonly _containerId = `container-${nextId++}`; | ||||
| private readonly _slot: ILifetimeSlot<this>; | ||||
|
|
r0 | |||
|
|
r1 | private _disposed: boolean; | ||
|
|
r0 | |||
|
|
r15 | constructor(services: DescriptorMap<S>, parentScope: ILifetimeManager[]) { | ||
|
|
r13 | this._services = services; | ||
|
|
r0 | this._disposed = false; | ||
|
|
r15 | this._scope = parentScope.concat(new LifetimeManager()); | ||
| // If this container is created inside the parent container scope, | ||||
| // allocated lifetime slot | ||||
| this._slot = parentScope.length ? | ||||
| parentScope[parentScope.length - 1].slot(this._containerId) : | ||||
| emptySlot<this>(); | ||||
| // store the container reference in the lifetime slot | ||||
| this._slot.store(this); | ||||
|
|
r0 | } | ||
|
|
r9 | private _assertNotDestroyed() { | ||
| if (this._disposed) | ||||
| throw new Error("The container is destroyed"); | ||||
|
|
r0 | } | ||
|
|
r9 | createChildBuilder(): IContainerBuilder<S, keyof S> { | ||
| this._assertNotDestroyed(); | ||||
|
|
r15 | return new ContainerBuilder(this._services, this._scope); | ||
|
|
r9 | } | ||
| resolve<K extends keyof S>(name: K): NonNullable<S[K]>; | ||||
| resolve<K extends keyof S, T>(name: K, def: T): NonNullable<S[K]> | T; | ||||
| resolve<K extends keyof S, T>(name: K, def?: T) { | ||||
| this._assertNotDestroyed(); | ||||
|
|
r15 | const context = new ActivationContext(this, this._scope, this._services); | ||
| return arguments.length === 1 ? | ||||
| context.resolve(name, []) : | ||||
| context.resolve(name, [], def); | ||||
|
|
r0 | } | ||
|
|
r15 | |||
|
|
r0 | destroy() { | ||
| if (this._disposed) | ||||
| return; | ||||
| this._disposed = true; | ||||
|
|
r15 | |||
| // destroy own scope | ||||
| this._scope[this._scope.length - 1].destroy(); | ||||
| // release lifetime slot if the container is destroyed before the parent | ||||
| // container. If this container is destroyed during the parent container | ||||
| // cleanup procedure this call will have no effect. | ||||
| this._slot.remove(); | ||||
|
|
r0 | } | ||
| } | ||||
