dynamicsmobile
Version:
Allows development of off-line mobile and web business apps over the Dynamics Mobile platform. More info on https://www.dynamicsmobile.com
117 lines • 4.94 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Container = void 0;
require("reflect-metadata");
const inject_1 = require("./inject");
const injectable_1 = require("./injectable");
const provider_1 = require("./provider");
const REFLECT_PARAMS = "design:paramtypes";
class Container {
constructor() {
this.providers = new Map();
this.replacedProviders = new Map();
this.singletonInstances = new Map();
}
clear() {
this.providers.clear();
this.replacedProviders.clear();
this.singletonInstances.clear();
}
addProvider(provider) {
this.assertInjectableIfClassProvider(provider);
if (!provider.replace) {
this.providers.set(provider.provide, provider);
}
else {
this.providers.delete(provider.provide);
this.replacedProviders.set(provider.provide, provider);
}
}
inject(type) {
let provider = this.replacedProviders.get(type);
if (!provider) {
provider = this.providers.get(type);
}
if (provider === undefined && !(type instanceof provider_1.InjectionToken)) {
provider = { provide: type, useClass: type };
this.assertInjectableIfClassProvider(provider);
}
return this.injectWithProvider(type, provider);
}
injectWithProvider(type, provider) {
if (!provider) {
throw new Error(`No provider for type ${this.getTokenName(type)}`);
}
if ((0, provider_1.isClassProvider)(provider)) {
return this.injectClass(provider);
}
else if ((0, provider_1.isValueProvider)(provider)) {
return this.injectValue(provider);
}
else if ((0, provider_1.isFactoryProvider)(provider)) {
// Factory provider by process of elimination
return this.injectFactory(provider);
}
else if ((0, provider_1.isSingletonProvider)(provider)) {
// Factory provider by process of elimination
return this.injectSingleton(provider);
}
var p = JSON.stringify(provider);
throw new Error(`Uknown DI provider for ${p}, type: ${type}`);
}
assertInjectableIfClassProvider(provider) {
if (((0, provider_1.isSingletonProvider)(provider) || (0, provider_1.isClassProvider)(provider)) && !(0, injectable_1.isInjectable)(provider.useClass)) {
throw new Error(`Cannot provide ${this.getTokenName(provider.provide)} using class ${this.getTokenName(provider.useClass)}, ${this.getTokenName(provider.useClass)} isn't injectable`);
}
}
injectClass(classProvider) {
const target = classProvider.useClass;
const params = this.getInjectedParams(target);
return Reflect.construct(target, params);
}
injectSingleton(classProvider) {
const target = classProvider.useClass;
var instance = this.singletonInstances.get(target.name);
if (!instance) {
const params = this.getInjectedParams(target);
instance = Reflect.construct(target, params);
this.singletonInstances.set(target.name, instance);
}
return instance;
}
injectValue(valueProvider) {
return valueProvider.useValue;
}
injectFactory(valueProvider) {
return valueProvider.useFactory();
}
getInjectedParams(target) {
const __argTypes = Reflect.getMetadata(REFLECT_PARAMS, target);
const argTypes = __argTypes;
if (argTypes === undefined) {
return [];
}
return argTypes.map((argType, index) => {
// The reflect-metadata API fails on circular dependencies, and will return undefined
// for the argument instead.
if (argType === undefined) {
throw new Error(`Injection error. Recursive dependency detected in constructor for type ${target.name} with parameter at index ${index}`);
}
const overrideToken = (0, inject_1.getInjectionToken)(target, index);
const actualToken = overrideToken === undefined ? argType : overrideToken;
let provider = this.replacedProviders.get(actualToken);
if (!provider)
provider = this.providers.get(actualToken);
if (!provider)
throw new Error(`No provider for type ${actualToken.name} in injectable ${target.name}'s constructor. Make sure the type for ${target.name}'s constructor argument #${index} is declared before type ${target.name}`);
return this.injectWithProvider(actualToken, provider);
});
}
getTokenName(token) {
return token instanceof provider_1.InjectionToken
? token.injectionIdentifier
: token.name;
}
}
exports.Container = Container;
//# sourceMappingURL=container.js.map