Containers - add ability to purge/release factories; override factories in scoped
This commit is contained in:
parent
cd9bec7c5e
commit
dab3d006c8
@ -47,6 +47,25 @@ export class Container {
|
|||||||
this.registerSingleton('injector', this)
|
this.registerSingleton('injector', this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Purge all factories and instances of the given key from this container.
|
||||||
|
* @param key
|
||||||
|
*/
|
||||||
|
purge(key: DependencyKey): this {
|
||||||
|
this.factories = this.factories.filter(x => !x.match(key))
|
||||||
|
this.release(key)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove all stored instances of the given key from this container.
|
||||||
|
* @param key
|
||||||
|
*/
|
||||||
|
release(key: DependencyKey): this {
|
||||||
|
this.instances = this.instances.filter(x => x.key !== key)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a basic instantiable class as a standard Factory with this container.
|
* Register a basic instantiable class as a standard Factory with this container.
|
||||||
* @param {Instantiable} dependency
|
* @param {Instantiable} dependency
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import {Container, MaybeDependency, MaybeFactory} from './Container'
|
import {Container, MaybeDependency, MaybeFactory} from './Container'
|
||||||
import {DependencyKey} from './types'
|
import {DependencyKey, Instantiable} from './types'
|
||||||
|
import {AbstractFactory} from './factory/AbstractFactory'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A container that uses some parent container as a base, but
|
* A container that uses some parent container as a base, but
|
||||||
@ -30,6 +31,8 @@ export class ScopedContainer extends Container {
|
|||||||
return new ScopedContainer(container)
|
return new ScopedContainer(container)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private resolveParentScope = true
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private parentContainer: Container,
|
private parentContainer: Container,
|
||||||
) {
|
) {
|
||||||
@ -38,11 +41,11 @@ export class ScopedContainer extends Container {
|
|||||||
}
|
}
|
||||||
|
|
||||||
hasInstance(key: DependencyKey): boolean {
|
hasInstance(key: DependencyKey): boolean {
|
||||||
return super.hasInstance(key) || this.parentContainer.hasInstance(key)
|
return super.hasInstance(key) || (this.resolveParentScope && this.parentContainer.hasInstance(key))
|
||||||
}
|
}
|
||||||
|
|
||||||
hasKey(key: DependencyKey): boolean {
|
hasKey(key: DependencyKey): boolean {
|
||||||
return super.hasKey(key) || this.parentContainer.hasKey(key)
|
return super.hasKey(key) || (this.resolveParentScope && this.parentContainer.hasKey(key))
|
||||||
}
|
}
|
||||||
|
|
||||||
getExistingInstance(key: DependencyKey): MaybeDependency {
|
getExistingInstance(key: DependencyKey): MaybeDependency {
|
||||||
@ -51,7 +54,9 @@ export class ScopedContainer extends Container {
|
|||||||
return inst
|
return inst
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.parentContainer.getExistingInstance(key)
|
if ( this.resolveParentScope ) {
|
||||||
|
return this.parentContainer.getExistingInstance(key)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve(key: DependencyKey): MaybeFactory<any> {
|
resolve(key: DependencyKey): MaybeFactory<any> {
|
||||||
@ -60,6 +65,77 @@ export class ScopedContainer extends Container {
|
|||||||
return factory
|
return factory
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.parentContainer?.resolve(key)
|
if ( this.resolveParentScope ) {
|
||||||
|
return this.parentContainer.resolve(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a basic instantiable class as a standard Factory with this container.
|
||||||
|
* @param {Instantiable} dependency
|
||||||
|
*/
|
||||||
|
register(dependency: Instantiable<any>): this {
|
||||||
|
return this.withoutParentScopes(() => super.register(dependency))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the given function as a factory within the container.
|
||||||
|
* @param {string} name - unique name to identify the factory in the container
|
||||||
|
* @param {function} producer - factory to produce a value
|
||||||
|
*/
|
||||||
|
registerProducer(name: DependencyKey, producer: () => any): this {
|
||||||
|
return this.withoutParentScopes(() => super.registerProducer(name, producer))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 {
|
||||||
|
return this.withoutParentScopes(() => super.registerNamed(name, dependency))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a value as a singleton in the container. It will not be instantiated, but
|
||||||
|
* can be injected by its unique name.
|
||||||
|
* @param {string} key - unique name to identify the singleton in the container
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
|
registerSingleton<T>(key: DependencyKey, value: T): this {
|
||||||
|
return this.withoutParentScopes(() => super.registerSingleton(key, value))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a static class to the container along with its already-instantiated
|
||||||
|
* instance that will be used to resolve the class.
|
||||||
|
* @param staticClass
|
||||||
|
* @param instance
|
||||||
|
*/
|
||||||
|
registerSingletonInstance<T>(staticClass: Instantiable<T>, instance: T): this {
|
||||||
|
return this.withoutParentScopes(() => super.registerSingletonInstance(staticClass, instance))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a given factory with the container.
|
||||||
|
* @param {AbstractFactory} factory
|
||||||
|
*/
|
||||||
|
registerFactory(factory: AbstractFactory<unknown>): this {
|
||||||
|
return this.withoutParentScopes(() => super.registerFactory(factory))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute a closure on this container, disabling parent-resolution.
|
||||||
|
* Effectively, the closure will have access to this container as if
|
||||||
|
* it were NOT a scoped container, and only contained its factories.
|
||||||
|
* @param closure
|
||||||
|
*/
|
||||||
|
withoutParentScopes<T>(closure: () => T): T {
|
||||||
|
const oldResolveParentScope = this.resolveParentScope
|
||||||
|
this.resolveParentScope = false
|
||||||
|
const value: T = closure()
|
||||||
|
this.resolveParentScope = oldResolveParentScope
|
||||||
|
return value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user