Added dependency injection
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
import 'reflect-metadata';
|
||||
import { Type } from './Util';
|
||||
import { FrontworkComponent } from '../Types/FrontworkComponent';
|
||||
|
||||
|
||||
/**
|
||||
* The Injector stores services and resolves requested instances.
|
||||
*/
|
||||
export const Injector = new class {
|
||||
|
||||
injectionQueue :any[] = []
|
||||
|
||||
rootInterface : Type<any>
|
||||
root : Type<any>
|
||||
rootModules : Type<any>[] = []
|
||||
|
||||
moduleObjs : {[key in string] : FrontworkComponent} = {}
|
||||
|
||||
/**
|
||||
* Resolves instances by injecting required services
|
||||
* @param {Type<any>} target
|
||||
* @returns {T}
|
||||
*/
|
||||
resolve<T>(target: Type<any>): T {
|
||||
// tokens are required dependencies, while injections are resolved tokens from the Injector
|
||||
|
||||
if(this.moduleObjs[target.name])
|
||||
return this.moduleObjs[target.name] as any
|
||||
|
||||
if(target.name === this.rootInterface.name || target.name === this.root.name){
|
||||
let modules = this.rootModules.map(m => {
|
||||
const module = new m()
|
||||
this.moduleObjs[m.name] = module
|
||||
return module
|
||||
})
|
||||
const rootobj = new this.root(modules);
|
||||
|
||||
this.moduleObjs[this.rootInterface.name] = rootobj
|
||||
this.moduleObjs[target.name] = rootobj
|
||||
this.injectionQueue.forEach(i => {
|
||||
i.target[i.where] = this.moduleObjs[i.what.name]
|
||||
})
|
||||
return rootobj
|
||||
}
|
||||
this.moduleObjs[target.name] = new target()
|
||||
return this.moduleObjs[target.name] as any
|
||||
|
||||
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,34 @@
|
||||
import { Injector } from "./Injector";
|
||||
import { Type, GenericClassDecorator } from "./Util";
|
||||
import { FrontworkComponent } from "../Types/FrontworkComponent";
|
||||
|
||||
/**
|
||||
* @returns {GenericClassDecorator<Type<any>>}
|
||||
* @constructor
|
||||
*/
|
||||
export const Module = (...args) : GenericClassDecorator<Type<any>> => {
|
||||
return (target: Type<any>) => {
|
||||
Injector.rootModules.push(target)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {GenericClassDecorator<Type<any>>}
|
||||
* @constructor
|
||||
*/
|
||||
export const RootComponent = (config : {
|
||||
rootInterface : Type<any>
|
||||
imports : Type<FrontworkComponent>[]
|
||||
}) : GenericClassDecorator<Type<any>> => {
|
||||
return (target: Type<any>) => {
|
||||
Injector.rootModules = config.imports
|
||||
Injector.rootInterface = config.rootInterface
|
||||
Injector.root = target
|
||||
}
|
||||
}
|
||||
|
||||
export const Inject = (type: any) => {
|
||||
return function (_this, key) {
|
||||
Injector.injectionQueue.push({what: type, target: _this, where:key})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* Type for what object is instances of
|
||||
*/
|
||||
export interface Type<T> {
|
||||
new(...args: any[]): T;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic `ClassDecorator` type
|
||||
*/
|
||||
export type GenericClassDecorator<T> = (target: T) => void;
|
||||
Reference in New Issue
Block a user