##// END OF EJS Templates
Removed ContextResolver, added DescriptoBuilder.wants(...), dependencies are declared statically
Removed ContextResolver, added DescriptoBuilder.wants(...), dependencies are declared statically

File last commit:

r1:a51ea59f0423 default
r4:d9e74143f779 default
Show More
Container.ts
79 lines | 3.2 KiB | video/mp2t | TypeScriptLexer
import { ActivationContext } from "./ActivationContext";
import { ActivationError } from "./ActivationError";
import { RegistrationMap, ContainerKeys, ServiceContainer, ContainerServices, ConfigurableServices, ConfigurableKeys, ServiceLocator, Descriptor} from "./interfaces";
import { LifetimeManager } from "./LifetimeManager";
import { each, isKey } from "./traits";
export class Container<S extends object > implements ServiceContainer<S> {
private readonly _services: Partial<RegistrationMap<ContainerServices<S>>>;
private readonly _lifetimeManager: LifetimeManager;
private readonly _cleanup: (() => void)[];
private _disposed: boolean;
constructor(parent?: Container<S>) {
this._services = Object.create(parent ? parent._services : null) as typeof this._services;
this._cleanup = [];
this._services.container = { activate: () => this as ServiceLocator<ContainerServices<S>>};
this._services.childContainer = { activate: () => this.createChildContainer() };
this._disposed = false;
this._lifetimeManager = new LifetimeManager();
}
register<K extends ConfigurableKeys<S>>(name: K, service: Descriptor<ContainerServices<S>, ConfigurableServices<S>[K]>): void;
register<K extends ConfigurableKeys<S>>(services: {[k in K]: Descriptor<ContainerServices<S>, ConfigurableServices<S>[k]>}): void;
register<K extends ConfigurableKeys<S>>(nameOrCollection: K | {[k in K]: Descriptor<ContainerServices<S>, ConfigurableServices<S>[k]>}, service?: RegistrationMap<ContainerServices<S>>[K]) {
if (!isKey(nameOrCollection)) {
each(nameOrCollection, (v, k) => this.register(k, v));
} else {
if (!service)
throw new Error("The service parameter must be a descriptor");
this._services[nameOrCollection] = service;
}
}
createChildContainer(): ServiceContainer<S> {
return new Container(this);
}
resolve<K extends ContainerKeys<S>>(name: K): NonNullable<ContainerServices<S>[K]>;
resolve<K extends ContainerKeys<S>>(name: K, def: ContainerServices<S>[K]): ContainerServices<S>[K];
resolve<K extends ContainerKeys<S>>(name: K, def?: ContainerServices<S>[K]): ContainerServices<S>[K] | undefined {
// TODO: add logging
// trace.debug("resolve {0}", name);
const d = this._services[name];
if (d === undefined) {
if (arguments.length > 1)
return def;
else
throw new Error(`Service '${String(name)}' isn't found`);
} else {
const context = new ActivationContext(this, this._services, String(name), d);
try {
return d.activate(context);
} catch (error) {
throw new ActivationError(name.toString(), context.getStack(), error);
}
}
}
createLifetime<T>() {
return this._lifetimeManager.create<T>();
}
destroy() {
return this.dispose();
}
dispose() {
if (this._disposed)
return;
this._disposed = true;
for (const f of this._cleanup)
f();
this._lifetimeManager.destroy();
}
}