UNPKG

ts.di

Version:

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

169 lines 6.8 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; require("reflect-metadata"); let Injector = Injector_1 = class Injector { static get(ctor) { return Injector_1.getWithFollower(ctor, undefined); } /* Set a class as @Singleton() and give it a custom \a value for future retrieving. * If there exist an instance of target class, and \a overwrite haven't set, * setting will be failed and function will return false. Otherwise, newIt singleton * instance will be set and true will be returned. */ static setSingleton(ctor, val, overwrite) { Injector_1.registerSingleton(ctor); if (!overwrite && ctor[Injector_1.singletonInstance]) { return false; } ctor[Injector_1.singletonInstance] = val; return true; } static isSingletonExist(ctor) { return !!ctor[Injector_1.singletonInstance]; } static getWithFollower(ctor, fllower) { // A class without @Injectable() decorated can be instantiate too // **But that is not recommended** if (Injector_1.strictDecorationCheck && !ctor[Injector_1.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_1.isSingleton]) { return ctor[Injector_1.singletonInstance] = ctor[Injector_1.singletonInstance] || Injector_1.create(ctor); } return Injector_1.create(ctor, fllower); } static create(ctor, follwer) { // If there is a factory for it if (ctor[Injector_1.factorSymbol]) return ctor[Injector_1.factorSymbol](); let argtypes = Reflect.getMetadata("design:paramtypes", ctor) || []; // If it depends on nothing, just newIt it. if (argtypes.length === 0) { return new ctor(); } // If it depends on something else, check if there is a dependency loop let newFollower; if (Injector_1.checkDependencyLoop) { if (follwer && follwer.indexOf(ctor) != -1) { throw new Error("Found dependency loop while trying to instantiate " + ctor.name + ". Please check your code."); } // Prepare for next dependency loop check newFollower = [ctor].concat(follwer); } // Instantiate the arguments it's constructor needs let args = []; for (let i = 0; i < argtypes.length; i++) { args.push(Injector_1.getWithFollower(argtypes[i], newFollower)); } // newIt it return new ctor(...args); } static registerInjectable(ctor) { ctor[Injector_1.isInjectable] = true; return ctor; } static registerSingleton(ctor) { ctor[Injector_1.isInjectable] = true; ctor[Injector_1.isSingleton] = true; return ctor; } static injectDecoratorFactor(undefOrTypeFunc) { if (undefOrTypeFunc) { return (target, propertyKey) => { Object.defineProperty(target, propertyKey, { get: () => { let obj = Injector_1.get(undefOrTypeFunc()); Object.defineProperty(target, propertyKey, obj); return obj; } }); }; } return (target, propertyKey) => { Object.defineProperty(target, propertyKey, { get: () => { let obj = Injector_1.get(Reflect.getMetadata("design:type", target, propertyKey)); Object.defineProperty(target, propertyKey, obj); return obj; } }); }; } static factorOfDecoratorFactor(ctor) { return (target, propertyKey, descriptor) => { ctor[Injector_1.factorSymbol] = target[propertyKey]; }; } }; Injector.factorSymbol = Symbol('Injector.factorSymbol'); Injector.isInjectable = Symbol('Injector.isInjectable'); Injector.isSingleton = Symbol('Injector.isSingleton'); Injector.singletonInstance = Symbol('Injector.singletonInstance'); Injector.checkDependencyLoop = false; // for performance considering, disable it by default. Injector.strictDecorationCheck = true; Injector = Injector_1 = __decorate([ Injectable() ], Injector); exports.Injector = Injector; /* \brief @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. * */ function Injectable() { return Injector.registerInjectable; } exports.Injectable = Injectable; /* @Singleton() marks a singleton class. * Use Injector.get() to get the instance of singleton class */ function Singleton() { return Injector.registerSingleton; } exports.Singleton = Singleton; /* \brief @Inject() marks a property as injected property * * Unlike @Injectable() unable to instantiate class having dependency loop, * @Inject(()=>Type) can instantiate dependencies like A->B->A as long as there is a * @Singleton() class among them. * */ function Inject(TypeFunc) { return Injector.injectDecoratorFactor(TypeFunc); } exports.Inject = Inject; /* \brief @FactorOf(Class) tell Injector to use it(this decorated function) to create instance of \a Class. * * Example : * \code ts * @Singleton() * class A { * // it's almost impossible to create A using our Injector. * // Because param val should provided by ourselves but not Injector. * // So a factor function to create it is necessary. * constructor(private val:number){} * } * class FactorUtils { * @FactorOf(A) * someFunctionToCreateA(){ * return {val:1234} * } * } * * Injector.get(A).val === 1234;// this will be true * \endcode */ function FactorOf(ctor) { return Injector.factorOfDecoratorFactor(ctor); } exports.FactorOf = FactorOf; var Injector_1; //# sourceMappingURL=Injector.js.map