ContainerBuilder.ts
70 lines
| 2.3 KiB
| video/mp2t
|
TypeScriptLexer
|
|
r5 | import { Container } from "./Container"; | |
| import { DescriptorBuilder } from "./DescriptorBuilder"; | |||
|
|
r13 | import { containerSelfDescriptor } from "./DescriptorImpl"; | |
| import { Descriptor, IContainerBuilder, IDescriptorBuilder, DescriptorMap, ServiceLocator, ILifetime, IDestroyable, ContainerServices, ContainerServicesConstraint } from "./interfaces"; | |||
|
|
r9 | import { emptyLifetime, LifetimeManager } from "./LifetimeManager"; | |
|
|
r11 | import { isDestroyable, prototype } from "./traits"; | |
|
|
r5 | ||
|
|
r9 | /** | |
| * Container builder used to prepare service descriptors and create a IoC container | |||
| */ | |||
|
|
r13 | export class ContainerBuilder<S extends ContainerServicesConstraint<S>, U extends keyof S> implements | |
|
|
r9 | IContainerBuilder<S, U> { | |
|
|
r5 | ||
| private _pending = 1; | |||
|
|
r13 | private readonly _services: DescriptorMap<ContainerServices<S>>; | |
|
|
r5 | ||
| private readonly _lifetimeManager = new LifetimeManager(); | |||
|
|
r9 | private readonly _lifetime: ILifetime<IDestroyable>; | |
|
|
r11 | constructor(parentServices: DescriptorMap<S> | null = null, lifetime?: ILifetime<IDestroyable>) { | |
|
|
r13 | this._services = { | |
| ...parentServices, | |||
| container: containerSelfDescriptor as any, | |||
| childContainer: containerSelfDescriptor as any | |||
| }; | |||
|
|
r9 | this._lifetimeManager = new LifetimeManager(); | |
| this._lifetime = lifetime ?? emptyLifetime(); | |||
|
|
r5 | } | |
|
|
r9 | createServiceBuilder<K extends U>(name: K): | |
| IDescriptorBuilder<S, S[K], Record<never, never>, U> { | |||
|
|
r5 | ||
| return new DescriptorBuilder(this._lifetimeManager, this._register(name), this._fail); | |||
|
|
r9 | ||
|
|
r5 | } | |
|
|
r9 | build(): ServiceLocator<S> { | |
|
|
r5 | this._assertBuilding(); | |
|
|
r9 | if (!this._complete()) | |
|
|
r5 | throw new Error("The configuration didn't complete."); | |
|
|
r9 | ||
|
|
r12 | const {remove, store} = this._lifetime(null); | |
|
|
r9 | ||
|
|
r12 | const container = new Container(this._services, this._lifetimeManager, remove); | |
|
|
r9 | ||
|
|
r12 | store(container); | |
|
|
r9 | ||
| return container; | |||
|
|
r5 | } | |
|
|
r9 | private readonly _register = <K extends U>(name: K) => | |
| (descriptor: Descriptor<S, S[K]>) => { | |||
| this._complete(); | |||
| this._services[name] = descriptor; | |||
| }; | |||
|
|
r5 | ||
| private readonly _fail = (ex: unknown) => { | |||
|
|
r9 | throw ex; | |
|
|
r5 | }; | |
| private _assertBuilding() { | |||
|
|
r9 | if (!this._pending) | |
| throw new Error("The descriptor builder is finalized"); | |||
|
|
r5 | } | |
| private _complete() { | |||
| return !(--this._pending); | |||
| } | |||
| } |
