ActivationContext.ts
111 lines
| 4.1 KiB
| video/mp2t
|
TypeScriptLexer
|
|
r15 | import { ActivationError, ActivationItem } from "./ActivationError"; | ||
| import { IActivationContext, DescriptorMap, ILifetimeManager, ILifetimeSlot, ServiceLocator, IContainerBuilder } from "../typings/interfaces"; | ||||
| import { argumentNotNull, each, prototype } from "./traits"; | ||||
| import { LifetimeManager } from "./LifetimeManager"; | ||||
| import { ContainerBuilder } from "./ContainerBuilder"; | ||||
|
|
r0 | |||
|
|
r9 | /** This object is created once per `Container.resolve` method call and used to | ||
|
|
r0 | * cache dependencies and to track created instances. The activation context | ||
| * tracks services with `context` activation type. | ||||
|
|
r9 | * | ||
| * @template S The service map used in the activation context, services from | ||||
| * this map are available to resolution. | ||||
| * @template U A set of keys from the service map which can be overridden in | ||||
| * this activation context. | ||||
|
|
r0 | */ | ||
|
|
r9 | export class ActivationContext<S> implements IActivationContext<S> { | ||
|
|
r0 | |||
|
|
r15 | private readonly _container: ServiceLocator<S>; | ||
|
|
r0 | |||
|
|
r15 | private readonly _contextScope: ILifetimeManager; | ||
|
|
r0 | |||
|
|
r15 | private _services: DescriptorMap<S>; | ||
|
|
r0 | |||
|
|
r15 | private readonly _scope: ILifetimeManager[]; | ||
|
|
r0 | |||
| /** Creates a new activation context with the specified parameters. | ||||
|
|
r1 | * @param containerLifetimeManager the container which starts the activation process | ||
|
|
r0 | * @param services the initial service registrations | ||
| * @param name the name of the service being activated, this parameter is | ||||
| * used for the debug purpose. | ||||
| * @param service the service to activate, this parameter is used for the | ||||
| * debug purpose. | ||||
| */ | ||||
|
|
r15 | constructor(container: ServiceLocator<S>, scope: ILifetimeManager[], services: DescriptorMap<S>, contextScope: ILifetimeManager = new LifetimeManager()) { | ||
| this._container = container; | ||||
| this._contextScope = contextScope; | ||||
|
|
r0 | this._services = services; | ||
|
|
r15 | this._scope = scope; | ||
|
|
r0 | } | ||
|
|
r15 | resolve<K extends keyof S>(name: K, stack: ActivationItem[]): NonNullable<S[K]>; | ||
| resolve<K extends keyof S, T>(name: K, stack: ActivationItem[], def: T): NonNullable<S[K]> | T; | ||||
| resolve<K extends keyof S, T>(name: K, stack: ActivationItem[], def?: T): NonNullable<S[K]> | T | undefined { | ||||
| const service = this._services[name]; | ||||
|
|
r0 | |||
|
|
r15 | if (service !== undefined) { | ||
| return service.activate( | ||||
| this, | ||||
| stack.concat({ | ||||
| name: name.toString(), | ||||
| descriptor: service.toString() | ||||
| }) | ||||
| ); | ||||
|
|
r0 | } else { | ||
|
|
r15 | if (arguments.length > 2) | ||
|
|
r0 | return def; | ||
| else | ||||
|
|
r15 | throw new Error("Service not found"); | ||
|
|
r0 | } | ||
| } | ||||
| /** | ||||
| * registers services local to the the activation context | ||||
| * | ||||
| * @name{string} the name of the service | ||||
| * @service{string} the service descriptor to register | ||||
| */ | ||||
|
|
r15 | private _register<K extends keyof S>(name: K, service: DescriptorMap<S>[K]) { | ||
|
|
r1 | argumentNotNull(name, "name"); | ||
|
|
r0 | |||
|
|
r9 | const d = this._services[name]; | ||
| if (d !== undefined && !d.configurable) | ||||
| throw new Error(`Service ${String(name)} can't be overridden`); | ||||
|
|
r1 | this._services[name] = service; | ||
|
|
r0 | } | ||
|
|
r15 | scopeSlot<T>(level: number, slotId: string | number): ILifetimeSlot<T> { | ||
| if (level < 0 || level >= this._scope.length) | ||||
| throw new Error("The scope level is out of range"); | ||||
| return this._scope[level].slot(slotId); | ||||
|
|
r14 | } | ||
|
|
r15 | hierarchySlot<T>(slotId: string | number): ILifetimeSlot<T> { | ||
| return this._scope[this._scope.length - 1].slot(slotId); | ||||
| } | ||||
| selfContainer(): ServiceLocator<S> { | ||||
| return this._container; | ||||
| } | ||||
| createChildContainer(): IContainerBuilder<S, keyof S> { | ||||
| return new ContainerBuilder(this._services, this._scope); | ||||
|
|
r14 | } | ||
| contextSlot<T>(slotId: string | number): ILifetimeSlot<T> { | ||||
|
|
r15 | return this._contextScope.slot(slotId); | ||
|
|
r0 | } | ||
|
|
r15 | withOverrides<X>(overrides: DescriptorMap<S>, action: () => X) { | ||
| const services = this._services; | ||||
| this._services = prototype(this._services); | ||||
| try { | ||||
| each(overrides, (v, k) => this._register(k, v)); | ||||
| return action(); | ||||
| } finally { | ||||
| this._services = services; | ||||
| } | ||||
|
|
r0 | } | ||
|
|
r11 | |||
|
|
r0 | } | ||
