You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
137 lines
4.7 KiB
137 lines
4.7 KiB
import {DependencyKey, Instantiable, StaticClass, TypedDependencyKey} from './types'
|
|
import NamedFactory from './factory/NamedFactory'
|
|
import {AbstractFactory} from './factory/AbstractFactory'
|
|
import {Factory} from './factory/Factory'
|
|
import {ClosureFactory} from './factory/ClosureFactory'
|
|
import {Collection, collect} from '../util/collection/Collection'
|
|
import {Subscription, Unsubscribe} from '../util/support/BehaviorSubject'
|
|
|
|
/** Simple type alias for a callback to a container's onResolve method. */
|
|
export type ContainerResolutionCallback<T> = (() => unknown) | ((t: T) => unknown)
|
|
|
|
/**
|
|
* Blueprint for newly-created containers.
|
|
*
|
|
* This is used to allow global helpers like `@Singleton()`
|
|
* or `@CLIDirective()` while still supporting multiple
|
|
* global Container instances at once.
|
|
*/
|
|
export class ContainerBlueprint {
|
|
private static instance?: ContainerBlueprint
|
|
|
|
public static getContainerBlueprint(): ContainerBlueprint {
|
|
if ( !this.instance ) {
|
|
this.instance = new ContainerBlueprint()
|
|
}
|
|
|
|
return this.instance
|
|
}
|
|
|
|
protected factories: Collection<(() => AbstractFactory<any>)> = collect()
|
|
|
|
protected constructableFactories: Collection<StaticClass<AbstractFactory<any>, any>> = collect()
|
|
|
|
protected resolutionCallbacks: Collection<{key: TypedDependencyKey<any>, callback: ContainerResolutionCallback<any>}> = collect()
|
|
|
|
/**
|
|
* Register some factory class with the container. Should take no construction params.
|
|
* @param factory
|
|
*/
|
|
registerFactory(factory: StaticClass<AbstractFactory<any>, any>): this {
|
|
this.constructableFactories.push(factory)
|
|
return this
|
|
}
|
|
|
|
/**
|
|
* Register a basic instantiable class as a standard Factory with this container,
|
|
* identified by a string name rather than static class.
|
|
* @param {string} name - unique name to identify the factory in the container
|
|
* @param {Instantiable} dependency
|
|
*/
|
|
registerNamed(name: string, dependency: Instantiable<any>): this {
|
|
this.factories.push(() => new NamedFactory(name, dependency))
|
|
return this
|
|
}
|
|
|
|
/**
|
|
* Register a basic instantiable class as a standard Factory with this container.
|
|
* @param {Instantiable} dependency
|
|
*/
|
|
register(dependency: Instantiable<any>): this {
|
|
this.factories.push(() => new Factory(dependency))
|
|
return this
|
|
}
|
|
|
|
/**
|
|
* Register a producer function as a ClosureFactory with this container.
|
|
* @param key
|
|
* @param producer
|
|
*/
|
|
registerProducer(key: DependencyKey, producer: () => any): this {
|
|
this.factories.push(() => new ClosureFactory(key, producer))
|
|
return this
|
|
}
|
|
|
|
/**
|
|
* Get an array of factory instances in the blueprint.
|
|
*/
|
|
resolve(): AbstractFactory<any>[] {
|
|
return this.factories.map(x => x()).all()
|
|
}
|
|
|
|
/**
|
|
* Subscribe to new factories being registered.
|
|
* Used by `Container` implementations to listen for factories being registered after the container is realized.
|
|
* @param sub
|
|
*/
|
|
resolve$(sub: Subscription<() => AbstractFactory<any>>): Unsubscribe {
|
|
return this.factories.push$(sub)
|
|
}
|
|
|
|
/**
|
|
* Register an onResolve callback to be added to all newly-created containers.
|
|
* @param key
|
|
* @param callback
|
|
*/
|
|
onResolve<T>(key: TypedDependencyKey<T>, callback: ContainerResolutionCallback<T>): this {
|
|
this.resolutionCallbacks.push({
|
|
key,
|
|
callback,
|
|
})
|
|
return this
|
|
}
|
|
|
|
/**
|
|
* Get an array of static Factory classes that need to be instantiated by
|
|
* the container itself.
|
|
*/
|
|
resolveConstructable(): StaticClass<AbstractFactory<any>, any>[] {
|
|
return this.constructableFactories.all()
|
|
}
|
|
|
|
/**
|
|
* Subscribe to new constructable factories being registered.
|
|
* Used by `Container` implementations to listen for factories registered after the container is realized.
|
|
* @param sub
|
|
*/
|
|
resolveConstructable$(sub: Subscription<StaticClass<AbstractFactory<any>, any>>): Unsubscribe {
|
|
return this.constructableFactories.push$(sub)
|
|
}
|
|
|
|
/**
|
|
* Get an array of DependencyKey-callback pairs to register with new containers.
|
|
*/
|
|
resolveResolutionCallbacks(): ({key: TypedDependencyKey<any>, callback: ContainerResolutionCallback<any>})[] {
|
|
return this.resolutionCallbacks.all()
|
|
}
|
|
|
|
/**
|
|
* Subscribe to new resolution callbacks being registered.
|
|
* Used by `Container` implementations to listen for callbacks registered after the container is realized.
|
|
* @param sub
|
|
*/
|
|
resolveResolutionCallbacks$(sub: Subscription<{key: TypedDependencyKey<any>, callback: ContainerResolutionCallback<any>}>): Unsubscribe {
|
|
return this.resolutionCallbacks.push$(sub)
|
|
}
|
|
}
|