UNPKG

dipperts

Version:

Dependency injection library for typescript.

77 lines (60 loc) 3.03 kB
import { IContainer, IScopeProvider } from "./IContainer"; import { ContainerBase, IScopedSingleton, isResolverWithOrigin, ResolverType, ISingletonByScopes } from "."; import { IContainerSpecification } from "./ContainerSpecification"; /** * Interface for a factory that creates a container. */ export interface IContainerFactory<TContainer extends IContainer> { /** * Create the container. */ create(): IScopeProvider<TContainer> & TContainer; /** * Create a new scope from an existing container. * @param scopeKey The key of the scope that is created. * @param scopedSingletons The singletons that were created as scoped in this container. */ createScope(oldContainer: ContainerBase<TContainer>, scopeKey: string, scopedSingletons: IScopedSingleton[]): IScopeProvider<TContainer> & TContainer; } /** * This factory creates a container from a set of container specs. */ export class ContainerSpecContainerFactory<TContainer extends IContainer> implements IContainerFactory<TContainer> { constructor(private containerSpecs: IContainerSpecification[]) { } public create(): IScopeProvider<TContainer> & TContainer { let container = this.createBase(); return <IScopeProvider<TContainer> & TContainer><any>container; } public createScope(oldContainer: ContainerBase<TContainer>, scopeKey: string, scopedSingletons: IScopedSingleton[]): IScopeProvider<TContainer> & TContainer { let container = this.createBase(); let anyContainer = container as any; let oldAnyContainer = oldContainer as any; for (let prop in container) { let value = anyContainer[prop] let oldValue = oldAnyContainer[prop] // if the property is a resolver // and a singleton at the same time if (isResolverWithOrigin(value) && value.resolverType === ResolverType.Singleton) { // find the matching scope singleton if present and scope it in the new container const origin = value.toOrigin(); const oldOrigin = oldValue.toOrigin(); const scopedSingleton = scopedSingletons.find(x => x.singleton === oldOrigin); if (scopedSingleton && scopedSingleton.scopeKey !== scopeKey) { container.unscopeSingleton(origin, oldOrigin); anyContainer[prop] = (scopedSingleton.singleton as any).toResolver(); } } } return <IScopeProvider<TContainer> & TContainer>anyContainer; } private createBase(): ContainerBase<TContainer> { let container = new ContainerBase<TContainer>(this); this.containerSpecs.forEach(containerSpec => { let containerExtension = containerSpec(container); container = Object.assign(container, containerExtension); }); return container; } }