import { Factory, FactoryDefinition } from './factory'; import { RegistryReader, Injection } from './registry'; import { Resolver } from './resolver'; import { Dict } from './dict'; interface Lookup { factory: Factory; instance: any; } export default class Container { private _registry: RegistryReader; private _resolver: Resolver; private _lookups: Dict; private _factoryDefinitionLookups: Dict>; constructor(registry: RegistryReader, resolver: Resolver = null) { this._registry = registry; this._resolver = resolver; this._lookups = {}; this._factoryDefinitionLookups = {}; } factoryFor(specifier: string): Factory { let factoryDefinition: FactoryDefinition = this._factoryDefinitionLookups[specifier]; if (!factoryDefinition) { if (this._resolver) { factoryDefinition = this._resolver.retrieve(specifier); } if (!factoryDefinition) { factoryDefinition = this._registry.registration(specifier); } if (factoryDefinition) { this._factoryDefinitionLookups[specifier] = factoryDefinition; } } if (!factoryDefinition) { return; } return this.buildFactory(specifier, factoryDefinition); } lookup(specifier: string): any { let singleton = (this._registry.registeredOption(specifier, 'singleton') !== false); if (singleton) { let lookup = this._lookups[specifier]; if (lookup) { return lookup.instance; } } let factory = this.factoryFor(specifier); if (!factory) { return; } if (this._registry.registeredOption(specifier, 'instantiate') === false) { return factory.class; } let instance = factory.create(); if (singleton && instance) { this._lookups[specifier] = { factory, instance }; } return instance; } defaultInjections(specifier: string): object { return {}; } teardown(): void { let specifiers = Object.keys(this._lookups); for (let i=0;i): Factory { let injections = this.buildInjections(specifier); return { class: factoryDefinition, teardown: (instance) => { if (factoryDefinition.teardown) { factoryDefinition.teardown(instance); } else { this.defaultTeardown(instance); } }, create(options) { let mergedOptions = Object.assign({}, injections, options); return factoryDefinition.create(mergedOptions); } } } }