2021-06-03 03:36:25 +00:00
|
|
|
import {AbstractFactory} from './AbstractFactory'
|
2021-06-02 01:59:40 +00:00
|
|
|
import {
|
|
|
|
DEPENDENCY_KEYS_METADATA_KEY,
|
|
|
|
DEPENDENCY_KEYS_PROPERTY_METADATA_KEY,
|
|
|
|
DependencyRequirement,
|
|
|
|
Instantiable,
|
2021-06-03 03:36:25 +00:00
|
|
|
PropertyDependency,
|
|
|
|
} from '../types'
|
|
|
|
import {Collection} from '../../util'
|
2021-06-02 01:59:40 +00:00
|
|
|
import 'reflect-metadata'
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Standard static-class factory. The token of this factory is a reference to a
|
|
|
|
* static class that is instantiated when the factory produces.
|
|
|
|
*
|
|
|
|
* Dependency keys are inferred from injection metadata on the constructor's params,
|
|
|
|
* as are the injected properties.
|
|
|
|
*
|
|
|
|
* @example
|
|
|
|
* ```typescript
|
|
|
|
* class A {
|
|
|
|
* constructor(
|
|
|
|
* protected readonly myService: MyService
|
|
|
|
* ) { }
|
|
|
|
* }
|
|
|
|
*
|
|
|
|
* const fact = new Factory(A)
|
|
|
|
*
|
|
|
|
* fact.produce([myServiceInstance], []) // => A { myService: myServiceInstance }
|
|
|
|
* ```
|
|
|
|
*/
|
2021-06-03 03:36:25 +00:00
|
|
|
export class Factory<T> extends AbstractFactory<T> {
|
2021-06-02 01:59:40 +00:00
|
|
|
constructor(
|
2021-06-03 03:36:25 +00:00
|
|
|
protected readonly token: Instantiable<T>,
|
2021-06-02 01:59:40 +00:00
|
|
|
) {
|
|
|
|
super(token)
|
|
|
|
}
|
|
|
|
|
|
|
|
produce(dependencies: any[], parameters: any[]): any {
|
|
|
|
return new this.token(...dependencies, ...parameters)
|
|
|
|
}
|
|
|
|
|
2021-06-03 03:36:25 +00:00
|
|
|
match(something: unknown): boolean {
|
2021-06-02 01:59:40 +00:00
|
|
|
return something === this.token // || (something?.name && something.name === this.token.name)
|
|
|
|
}
|
|
|
|
|
|
|
|
getDependencyKeys(): Collection<DependencyRequirement> {
|
|
|
|
const meta = Reflect.getMetadata(DEPENDENCY_KEYS_METADATA_KEY, this.token)
|
2021-06-03 03:36:25 +00:00
|
|
|
if ( meta ) {
|
|
|
|
return meta
|
|
|
|
}
|
2021-06-02 01:59:40 +00:00
|
|
|
return new Collection<DependencyRequirement>()
|
|
|
|
}
|
|
|
|
|
|
|
|
getInjectedProperties(): Collection<PropertyDependency> {
|
|
|
|
const meta = new Collection<PropertyDependency>()
|
|
|
|
let currentToken = this.token
|
|
|
|
|
|
|
|
do {
|
|
|
|
const loadedMeta = Reflect.getMetadata(DEPENDENCY_KEYS_PROPERTY_METADATA_KEY, currentToken)
|
2021-06-03 03:36:25 +00:00
|
|
|
if ( loadedMeta ) {
|
|
|
|
meta.concat(loadedMeta)
|
|
|
|
}
|
2021-06-02 01:59:40 +00:00
|
|
|
currentToken = Object.getPrototypeOf(currentToken)
|
|
|
|
} while (Object.getPrototypeOf(currentToken) !== Function.prototype && Object.getPrototypeOf(currentToken) !== Object.prototype)
|
|
|
|
|
|
|
|
return meta
|
|
|
|
}
|
|
|
|
}
|