DI: add logic for static class overrides

This commit is contained in:
Garrett Mills 2021-11-26 14:31:18 -06:00
parent 6fc901b3ec
commit bf4a675faa
2 changed files with 66 additions and 1 deletions

View File

@ -1,4 +1,12 @@
import {DependencyKey, InstanceRef, Instantiable, isInstantiable, StaticClass, TypedDependencyKey} from './types'
import {
DependencyKey,
InstanceRef,
Instantiable,
isInstantiable,
StaticClass,
StaticInstantiable,
TypedDependencyKey,
} from './types'
import {AbstractFactory} from './factory/AbstractFactory'
import {collect, Collection, globalRegistry, logIfDebugging} from '../util'
import {Factory} from './factory/Factory'
@ -66,6 +74,12 @@ export class Container {
*/
protected instances: Collection<InstanceRef> = new Collection<InstanceRef>()
/**
* Collection of static-class overrides registered with this container.
* @protected
*/
protected staticOverrides: Collection<{ base: StaticInstantiable<any>, override: StaticInstantiable<any> }> = new Collection<{base: StaticInstantiable<any>; override: StaticInstantiable<any>}>()
/**
* Collection of callbacks waiting for a dependency key to be resolved.
* @protected
@ -110,6 +124,52 @@ export class Container {
return this
}
/**
* Register a static class as an override of some base class.
* @param base
* @param override
*/
registerStaticOverride<T>(base: StaticInstantiable<T>, override: StaticInstantiable<T>): this {
if ( this.hasStaticOverride(base) ) {
throw new DuplicateFactoryKeyError(base)
}
this.staticOverrides.push({
base,
override,
})
return this
}
/** Returns true if a static override exists for the given base class. */
hasStaticOverride<T>(base: StaticInstantiable<T>): boolean {
return this.staticOverrides.where('base', '=', base).isNotEmpty()
}
/**
* Get the static class overriding the base class.
* @param base
*/
getStaticOverride<T>(base: StaticInstantiable<T>): StaticInstantiable<T> {
const override = this.staticOverrides.firstWhere('base', '=', base)
if ( override ) {
return override.override
}
return base
}
/**
* Get the registered instance of the static override of a given class.
* @param base
* @param parameters
*/
makeByStaticOverride<T>(base: StaticInstantiable<T>, ...parameters: any[]): T {
const key = this.getStaticOverride(base)
return this.make(key, ...parameters)
}
/**
* Register the given function as a factory within the container.
* @param {string} name - unique name to identify the factory in the container

View File

@ -38,6 +38,11 @@ export function isInstantiableOf<T>(what: unknown, type: StaticClass<T, any>): w
*/
export type StaticClass<T, T2> = Function & {prototype: T} & T2 // eslint-disable-line @typescript-eslint/ban-types
/**
* Type that identifies a value as a static class that instantiates to itself
*/
export type StaticInstantiable<T> = StaticClass<T, Instantiable<T>>
/**
* Returns true if the parameter is a static class.
* @param something