2022-09-26 16:34:23 +00:00
|
|
|
import {DependencyKey, DependencyRequirement, Instantiable, PropertyDependency} from '../types'
|
|
|
|
import {Collection, logIfDebugging} from '../../util'
|
|
|
|
import {getPropertyInjectionMetadata} from '../decorator/getPropertyInjectionMetadata'
|
2021-06-02 01:59:40 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Abstract base class for dependency container factories.
|
|
|
|
* @abstract
|
|
|
|
*/
|
2021-06-03 03:36:25 +00:00
|
|
|
export abstract class AbstractFactory<T> {
|
2021-06-02 01:59:40 +00:00
|
|
|
protected constructor(
|
|
|
|
/**
|
|
|
|
* Token that was registered for this factory. In most cases, this is the static
|
|
|
|
* form of the item that is to be produced by this factory.
|
|
|
|
* @var
|
|
|
|
* @protected
|
|
|
|
*/
|
2021-06-03 03:36:25 +00:00
|
|
|
protected token: DependencyKey,
|
2021-06-02 01:59:40 +00:00
|
|
|
) {}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Produce an instance of the token.
|
|
|
|
* @param {Array} dependencies - the resolved dependencies, in order
|
|
|
|
* @param {Array} parameters - the bound constructor parameters, in order
|
|
|
|
*/
|
2021-06-03 03:36:25 +00:00
|
|
|
abstract produce(dependencies: any[], parameters: any[]): T
|
2021-06-02 01:59:40 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Should return true if the given identifier matches the token for this factory.
|
|
|
|
* @param something
|
|
|
|
* @return boolean
|
|
|
|
*/
|
2021-06-03 03:36:25 +00:00
|
|
|
abstract match(something: unknown): boolean
|
2021-06-02 01:59:40 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the dependency requirements required by this factory's token.
|
|
|
|
* @return Collection<DependencyRequirement>
|
|
|
|
*/
|
|
|
|
abstract getDependencyKeys(): Collection<DependencyRequirement>
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the property dependencies that should be injected to the created instance.
|
|
|
|
* @return Collection<PropertyDependency>
|
|
|
|
*/
|
|
|
|
abstract getInjectedProperties(): Collection<PropertyDependency>
|
2022-08-11 02:53:56 +00:00
|
|
|
|
2022-09-26 16:34:23 +00:00
|
|
|
/** Helper method that returns all `@Inject()`'ed properties for a token and its prototypical ancestors. */
|
|
|
|
protected getInjectedPropertiesForPrototypeChain(token: Instantiable<any>): Collection<PropertyDependency> {
|
|
|
|
const meta = new Collection<PropertyDependency>()
|
|
|
|
|
|
|
|
do {
|
|
|
|
const loadedMeta = getPropertyInjectionMetadata(token)
|
|
|
|
if ( loadedMeta ) {
|
|
|
|
meta.concat(loadedMeta)
|
|
|
|
}
|
|
|
|
token = Object.getPrototypeOf(token)
|
|
|
|
logIfDebugging('extollo.di.injection', 'next currentToken:', token)
|
|
|
|
} while (token !== Function.prototype && token !== Object.prototype)
|
|
|
|
|
|
|
|
return meta
|
|
|
|
}
|
|
|
|
|
2022-08-11 02:53:56 +00:00
|
|
|
/**
|
|
|
|
* Get a human-readable name of the token this factory produces.
|
|
|
|
* This is meant for debugging output only.
|
|
|
|
*/
|
|
|
|
public getTokenName(): string {
|
|
|
|
if ( typeof this.token === 'string' ) {
|
|
|
|
return this.token
|
|
|
|
}
|
|
|
|
|
2022-08-20 21:21:06 +00:00
|
|
|
return this.token?.name ?? '(unknown token)'
|
2022-08-11 02:53:56 +00:00
|
|
|
}
|
2021-06-02 01:59:40 +00:00
|
|
|
}
|