tsioc
Version:
tsioc is AOP, Ioc container, via typescript decorator
443 lines (441 loc) • 14.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
require("reflect-metadata");
var types_1 = require("./types");
var Registration_1 = require("./Registration");
var index_1 = require("./utils/index");
var index_2 = require("./aop/index");
var index_3 = require("./core/index");
var index_4 = require("./logs/index");
/**
* Container.
*/
var Container = /** @class */ (function () {
function Container() {
this.init();
}
/**
* Retrieves an instance from the container based on the provided token.
*
* @template T
* @param {Token<T>} token
* @param {string} [alias]
* @param {T} [notFoundValue]
* @returns {T}
* @memberof Container
*/
Container.prototype.get = function (token, alias) {
return this.resolve(alias ? this.getTokenKey(token, alias) : token);
};
/**
* resolve type instance with token and param provider.
*
* @template T
* @param {Token<T>} token
* @param {T} [notFoundValue]
* @param {...Providers[]} providers
* @memberof Container
*/
Container.prototype.resolve = function (token) {
var providers = [];
for (var _i = 1; _i < arguments.length; _i++) {
providers[_i - 1] = arguments[_i];
}
var key = this.getTokenKey(token);
if (!this.hasRegister(key)) {
console.error('have not register', key);
return null;
}
var factory = this.factories.get(key);
return factory.apply(void 0, providers);
};
/**
* clear cache.
*
* @param {Type<any>} targetType
* @memberof IContainer
*/
Container.prototype.clearCache = function (targetType) {
this.get(index_1.symbols.ICacheManager).destroy(targetType);
};
/**
* get token.
*
* @template T
* @param {Token<T>} token
* @param {string} [alias]
* @returns {Token<T>}
* @memberof Container
*/
Container.prototype.getToken = function (token, alias) {
if (token instanceof Registration_1.Registration) {
return token;
}
else {
if (alias && index_1.isFunction(token)) {
return new Registration_1.Registration(token, alias);
}
return token;
}
};
/**
* get tocken key.
*
* @template T
* @param {Token<T>} token
* @param {string} [alias]
* @returns {SymbolType<T>}
* @memberof Container
*/
Container.prototype.getTokenKey = function (token, alias) {
if (token instanceof Registration_1.Registration) {
return token.toString();
}
else {
if (alias) {
return new Registration_1.Registration(token, alias).toString();
}
return token;
}
};
/**
* register type.
* @abstract
* @template T
* @param {Token<T>} token
* @param {T} [value]
* @returns {this}
* @memberOf Container
*/
Container.prototype.register = function (token, value) {
this.registerFactory(token, value);
return this;
};
/**
* has register the token or not.
*
* @template T
* @param {Token<T>} token
* @param {string} [alias]
* @returns {boolean}
* @memberof Container
*/
Container.prototype.has = function (token, alias) {
var key = this.getTokenKey(token, alias);
return this.hasRegister(key);
};
/**
* has register type.
*
* @template T
* @param {SymbolType<T>} key
* @returns
* @memberof Container
*/
Container.prototype.hasRegister = function (key) {
return this.factories.has(key);
};
/**
* unregister the token
*
* @template T
* @param {Token<T>} token
* @returns {this}
* @memberof Container
*/
Container.prototype.unregister = function (token) {
var key = this.getTokenKey(token);
if (this.hasRegister(key)) {
this.factories.delete(key);
}
return this;
};
/**
* register stingleton type.
* @abstract
* @template T
* @param {Token<T>} token
* @param {Factory<T>} [value]
* @returns {this}
* @memberOf Container
*/
Container.prototype.registerSingleton = function (token, value) {
this.registerFactory(token, value, true);
return this;
};
/**
* bind provider.
*
* @template T
* @param {Token<T>} provide
* @param {Token<T>} provider
* @returns {this}
* @memberof Container
*/
Container.prototype.bindProvider = function (provide, provider) {
var _this = this;
var provideKey = this.getTokenKey(provide);
var factory;
if (index_1.isToken(provider)) {
factory = function () {
var providers = [];
for (var _i = 0; _i < arguments.length; _i++) {
providers[_i] = arguments[_i];
}
return _this.resolve.apply(_this, [provider].concat(providers));
};
}
else {
if (index_1.isFunction(provider)) {
factory = function () {
var providers = [];
for (var _i = 0; _i < arguments.length; _i++) {
providers[_i] = arguments[_i];
}
return provider.apply(void 0, [_this].concat(providers));
};
}
else {
factory = function () {
return provider;
};
}
}
if (index_1.isClass(provider)) {
this.provideTypes.set(provide, provider);
}
else if (index_1.isToken(provider)) {
var token = provider;
while (this.provideTypes.has(token) && !index_1.isClass(token)) {
token = this.provideTypes.get(token);
if (index_1.isClass(token)) {
this.provideTypes.set(provide, token);
break;
}
}
}
this.factories.set(provideKey, factory);
return this;
};
/**
* get token implements class type.
*
* @template T
* @param {Token<T>} token
* @returns {Type<T>}
* @memberof Container
*/
Container.prototype.getTokenImpl = function (token) {
if (index_1.isClass(token)) {
return token;
}
if (this.provideTypes.has(token)) {
return this.provideTypes.get(token);
}
return null;
};
/**
* get life scope of container.
*
* @returns {LifeScope}
* @memberof IContainer
*/
Container.prototype.getLifeScope = function () {
return this.get(index_1.symbols.LifeScope);
};
/**
* invoke method async.
*
* @template T
* @param {Token<any>} token
* @param {(string | symbol)} propertyKey
* @param {*} [instance]
* @param {...Providers[]} providers
* @returns {Promise<T>}
* @memberof Container
*/
Container.prototype.invoke = function (token, propertyKey, instance) {
var providers = [];
for (var _i = 3; _i < arguments.length; _i++) {
providers[_i - 3] = arguments[_i];
}
return (_a = this.get(index_1.symbols.IMethodAccessor)).invoke.apply(_a, [token, propertyKey, instance].concat(providers));
var _a;
};
/**
* invoke method.
*
* @template T
* @param {Token<any>} token
* @param {(string | symbol)} propertyKey
* @param {*} [instance]
* @param {...Providers[]} providers
* @returns {T}
* @memberof Container
*/
Container.prototype.syncInvoke = function (token, propertyKey, instance) {
var providers = [];
for (var _i = 3; _i < arguments.length; _i++) {
providers[_i - 3] = arguments[_i];
}
return (_a = this.get(index_1.symbols.IMethodAccessor)).syncInvoke.apply(_a, [token, propertyKey, instance].concat(providers));
var _a;
};
Container.prototype.createSyncParams = function (params) {
var providers = [];
for (var _i = 1; _i < arguments.length; _i++) {
providers[_i - 1] = arguments[_i];
}
return (_a = this.get(index_1.symbols.IMethodAccessor)).createSyncParams.apply(_a, [params].concat(providers));
var _a;
};
Container.prototype.createParams = function (params) {
var providers = [];
for (var _i = 1; _i < arguments.length; _i++) {
providers[_i - 1] = arguments[_i];
}
return (_a = this.get(index_1.symbols.IMethodAccessor)).createParams.apply(_a, [params].concat(providers));
var _a;
};
Container.prototype.cacheDecorator = function (map, action) {
if (!map.has(action.name)) {
map.set(action.name, action);
}
};
Container.prototype.init = function () {
var _this = this;
this.factories = new index_1.MapSet();
this.singleton = new index_1.MapSet();
this.provideTypes = new index_1.MapSet();
this.bindProvider(index_1.symbols.IContainer, function () { return _this; });
index_3.registerCores(this);
index_2.registerAops(this);
index_4.registerLogs(this);
};
Container.prototype.registerFactory = function (token, value, singleton) {
var key = this.getTokenKey(token);
if (this.factories.has(key)) {
return;
}
var classFactory;
if (!index_1.isUndefined(value)) {
if (index_1.isFunction(value)) {
if (index_1.isClass(value)) {
classFactory = this.createTypeFactory(key, value, singleton);
}
else {
classFactory = this.createCustomFactory(key, value, singleton);
}
}
else if (singleton && value !== undefined) {
classFactory = this.createCustomFactory(key, function () { return value; }, singleton);
}
}
else if (!index_1.isString(token) && !index_1.isSymbol(token)) {
var ClassT = (token instanceof Registration_1.Registration) ? token.getClass() : token;
if (index_1.isClass(ClassT)) {
classFactory = this.createTypeFactory(key, ClassT, singleton);
}
}
if (classFactory) {
this.factories.set(key, classFactory);
}
};
Container.prototype.createCustomFactory = function (key, factory, singleton) {
var _this = this;
return singleton ?
function () {
var providers = [];
for (var _i = 0; _i < arguments.length; _i++) {
providers[_i] = arguments[_i];
}
if (_this.singleton.has(key)) {
return _this.singleton.get(key);
}
var instance = factory.apply(void 0, [_this].concat(providers));
_this.singleton.set(key, instance);
return instance;
}
: function () {
var providers = [];
for (var _i = 0; _i < arguments.length; _i++) {
providers[_i] = arguments[_i];
}
return factory.apply(void 0, [_this].concat(providers));
};
};
Container.prototype.createTypeFactory = function (key, ClassT, singleton) {
var _this = this;
if (!Reflect.isExtensible(ClassT)) {
return null;
}
var lifeScope = this.getLifeScope();
var parameters = lifeScope.getConstructorParameters(ClassT);
if (!singleton) {
singleton = lifeScope.isSingletonType(ClassT);
}
var factory = function () {
var providers = [];
for (var _i = 0; _i < arguments.length; _i++) {
providers[_i] = arguments[_i];
}
if (singleton && _this.singleton.has(key)) {
return _this.singleton.get(key);
}
if (providers.length < 1) {
var lifecycleData = {
targetType: ClassT
};
lifeScope.execute(index_3.DecoratorType.Class, lifecycleData, index_3.CoreActions.componentCache);
if (lifecycleData.execResult && lifecycleData.execResult instanceof ClassT) {
return lifecycleData.execResult;
}
}
lifeScope.execute(index_3.DecoratorType.Class, {
targetType: ClassT
}, types_1.IocState.runtime);
var args = _this.createSyncParams.apply(_this, [parameters].concat(providers));
lifeScope.execute(index_3.DecoratorType.Class, {
targetType: ClassT,
args: args,
params: parameters,
providers: providers
}, index_3.CoreActions.beforeConstructor);
var instance = new (ClassT.bind.apply(ClassT, [void 0].concat(args)))();
lifeScope.execute(index_3.DecoratorType.Class, {
target: instance,
targetType: ClassT,
args: args,
params: parameters,
providers: providers
}, index_3.CoreActions.afterConstructor);
lifeScope.execute(index_3.DecoratorType.Property, {
target: instance,
targetType: ClassT,
providers: providers
});
lifeScope.execute(index_3.DecoratorType.Method, {
target: instance,
targetType: ClassT,
providers: providers
});
if (singleton) {
_this.singleton.set(key, instance);
}
else if (providers.length < 1) {
lifeScope.execute(index_3.DecoratorType.Class, {
target: instance,
targetType: ClassT
}, index_3.CoreActions.componentCache);
}
return instance;
};
lifeScope.execute(index_3.DecoratorType.Class, {
targetType: ClassT
}, types_1.IocState.design);
return factory;
};
return Container;
}());
exports.Container = Container;
//# sourceMappingURL=sourcemaps/Container.js.map