UNPKG

zhtsdi

Version:

Typescript写的依赖注入库。An dependency-injection library for TypeScript.

92 lines (74 loc) 3.1 kB
/** * Created by Weizehua on 2017/1/13. */ import "reflect-metadata" interface Newable<T> extends Function { new(...args): T; } @Injectable() export class Injector { // private static _instance = new Injector(); private static isInjectable = Symbol('Injector:is-injectable'); private static isSingleton = Symbol('Injector:is-singleton'); private static singletonInstance = Symbol('Injector:singleton-instance'); public static checkDependencyLoop = true; public static strictDecorationCheck = true; private constructor() { } static get<T>(ctor: Newable<T>): T { // A class without @Injectable() decorated can be instantiate too // **But that is not recommended** if (Injector.strictDecorationCheck && !ctor[Injector.isInjectable]) { throw new Error("To get a instance of " + ctor.name + ", you should decorate it with @Injectable().") } // There is a different instantiation for Singleton class. if (ctor[Injector.isSingleton]) return ctor[Injector.singletonInstance] = ctor[Injector.singletonInstance] || Injector.create(ctor); return Injector.create(ctor); } private static create<T>(ctor: Newable<T>, follwer?: Function[]): T { let argtypes = Reflect.getMetadata("design:paramtypes", ctor) || []; // If it depends on nothing, just new it. if (argtypes.length === 0) { return new ctor(); } // If it depends on something else, check if there is a dependency loop if (Injector.checkDependencyLoop && follwer && follwer.find(val => { return val === ctor; })) { throw new Error("Found dependency loop while trying to instantiate " + ctor.name + ". Please check your code."); } // Prepare for next dependency loop check let newFollower = (<Function[]>[ctor]).concat(follwer); // Instantiate the arguments it needs let args = []; for (let i = 0; i < argtypes.length; i++) { args.push(Injector.get(argtypes[i]), newFollower); } return new ctor(...args); } static injectableDecorator<T>(ctor: Newable<T>): Newable<T> { ctor[Injector.isInjectable] = true; return ctor; } static singletonDecorator<T>(ctor: Newable<T>): Newable<T> { ctor[Injector.isInjectable] = true; ctor[Injector.isSingleton] = true; return ctor; } } /* @Injectable() marks a class injectable * Use Injector.get() to get a instance of that class * Calling Injector.get() multiple times on a @Injectable() decorated class * will produce different instances. */ export function Injectable(): ClassDecorator { return Injector.injectableDecorator; } /* @Singleton() marks a singleton class. * Use Injector.get() to get the instance of singleton class */ export function Singleton(): ClassDecorator { return Injector.singletonDecorator; }