Added dependency injection

This commit is contained in:
peter
2020-01-22 00:58:12 +01:00
parent 030908376b
commit e4a6972884
27 changed files with 1769 additions and 208 deletions
+50
View File
@@ -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
}
};
+34
View File
@@ -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})
}
}
+11
View File
@@ -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;