@asuka/di
Version:
Dependencies inject library
185 lines • 7.67 kB
JavaScript
import { __read, __spread, __values } from "tslib";
import { ReflectiveProvider } from './injector-provider';
import { InjectionProvider } from './provider';
var Injector = (function () {
function Injector(parent) {
if (parent === void 0) { parent = null; }
this.parent = parent;
this.provider = new InjectionProvider();
this.resolvedProviders = new Map();
this.providersCache = new Map();
}
Injector.prototype.addProvider = function (provider) {
return this.provider.addProvider(provider);
};
Injector.prototype.addProviders = function (providers) {
var e_1, _a;
try {
for (var providers_1 = __values(providers), providers_1_1 = providers_1.next(); !providers_1_1.done; providers_1_1 = providers_1.next()) {
var provider = providers_1_1.value;
this.provider.addProvider(provider);
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (providers_1_1 && !providers_1_1.done && (_a = providers_1.return)) _a.call(providers_1);
}
finally { if (e_1) throw e_1.error; }
}
return this;
};
Injector.prototype.getInstance = function (provider) {
return this._getInstance(provider, true);
};
Injector.prototype.resolveAndInstantiate = function (provider) {
return this._getInstance(provider, false);
};
Injector.prototype.createChild = function (providers) {
var e_2, _a;
var childInjector = new Injector(this);
try {
for (var providers_2 = __values(providers), providers_2_1 = providers_2.next(); !providers_2_1.done; providers_2_1 = providers_2.next()) {
var provider = providers_2_1.value;
childInjector.provider.addProvider(provider);
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (providers_2_1 && !providers_2_1.done && (_a = providers_2.return)) _a.call(providers_2);
}
finally { if (e_2) throw e_2.error; }
}
return childInjector;
};
Injector.prototype.resolveReflectiveProvider = function (provider) {
var _a;
var reflectiveProvider = null;
if (this.provider.findProviderByToken((_a = provider.provide, (_a !== null && _a !== void 0 ? _a : provider)))) {
if (this.providersCache.has(provider)) {
return this.providersCache.get(provider);
}
reflectiveProvider = new ReflectiveProvider(provider);
this.providersCache.set(provider, reflectiveProvider);
}
return reflectiveProvider;
};
Injector.prototype._getInstance = function (provider, useCache) {
var injector = this;
var instance = null;
var reflectiveProvider = null;
var deps = this._findDeps(provider);
while (injector) {
reflectiveProvider = injector.resolveReflectiveProvider(provider);
if (!reflectiveProvider) {
injector = injector.parent;
continue;
}
if (injector.resolvedProviders.has(reflectiveProvider)) {
if (deps) {
if (useCache && (injector === this || this._checkDepenciesClean(injector, deps))) {
instance = injector.resolvedProviders.get(reflectiveProvider);
}
else {
instance = this._resolveByReflectiveProvider(reflectiveProvider, false, this);
if (useCache) {
this.resolvedProviders.set(reflectiveProvider, instance);
}
}
}
else {
instance = injector.resolvedProviders.get(reflectiveProvider);
}
break;
}
instance = injector._resolveByReflectiveProvider(reflectiveProvider, useCache, this);
if (instance) {
if (useCache) {
injector.resolvedProviders.set(reflectiveProvider, instance);
}
break;
}
injector = injector.parent;
}
if (!instance) {
reflectiveProvider = new ReflectiveProvider(provider);
throw new TypeError("No provider for " + reflectiveProvider.name + "!");
}
return instance;
};
Injector.prototype._resolveByReflectiveProvider = function (reflectiveProvider, useCache, leaf) {
var _a;
if (useCache === void 0) { useCache = true; }
if (leaf === void 0) { leaf = this; }
var _b;
var instance = null;
var provider = reflectiveProvider.provider, name = reflectiveProvider.name;
if (typeof provider === 'function') {
var deps = (_b = Reflect.getMetadata('design:paramtypes', provider), (_b !== null && _b !== void 0 ? _b : []));
var depsInstance = deps.map(function (dep) { return leaf._getInstance(leaf._findExisting(dep), useCache); });
instance = new (provider.bind.apply(provider, __spread([void 0], depsInstance)))();
}
else if (provider.useValue) {
instance = provider.useValue;
}
else if (provider.useClass) {
instance = leaf._getInstance(provider.useClass, useCache);
}
else if (provider.useFactory) {
var deps = [];
if (provider.deps) {
deps = provider.deps.map(function (dep) { return leaf._getInstance(leaf._findExisting(dep), useCache); });
}
instance = (_a = provider).useFactory.apply(_a, __spread(deps));
}
else if (provider.useExisting) {
instance = leaf._getInstance(this._findExisting(provider.useExisting), useCache);
}
if (!instance) {
throw new TypeError("Can not resolve " + name + ", it's not a valid provider");
}
return instance;
};
Injector.prototype._findExisting = function (token) {
var _a;
var provider = null;
var injector = this;
while (injector) {
provider = injector.provider.findProviderByToken(token);
if (provider) {
break;
}
injector = injector.parent;
}
if (!provider) {
throw new TypeError("No provider for " + (_a = token.name, (_a !== null && _a !== void 0 ? _a : token.toString())));
}
return provider;
};
Injector.prototype._findDeps = function (provider) {
return typeof provider === 'function'
? Reflect.getMetadata('design:paramtypes', provider)
: provider.useClass
? Reflect.getMetadata('design:paramtypes', provider.useClass)
: provider.deps
? provider.deps
: null;
};
Injector.prototype._checkDepenciesClean = function (leaf, deps) {
var _this = this;
return deps.every(function (dep) {
var depInLeaf = leaf._findExisting(dep);
var depInRoot = _this._findExisting(dep);
var isEqual = depInLeaf === depInRoot;
var deps = _this._findDeps(depInLeaf);
if (deps) {
return _this._checkDepenciesClean(leaf, deps) && isEqual;
}
return isEqual;
});
};
return Injector;
}());
export { Injector };
//# sourceMappingURL=injector.js.map