##// END OF EJS Templates
Completely removed IoC annotations...
cin -
r135:03e32ec7c20b ioc ts support
parent child
Show More
@@ -0,0 +1,63
1 import { Descriptor, PartialServiceMap, ILifetime, ContainerKeys } from "../interfaces";
2 import { ActivationContext } from "../ActivationContext";
3 import { each } from "../../safe";
4 import { DependencyOptions, LazyDependencyOptions, Resolver } from "./interfaces";
5
6 export interface DescriptorImplArgs<S extends object, T> {
7 lifetime: ILifetime;
8
9 factory: (resolve: Resolver<S>) => T;
10
11 cleanup?: (item: T) => void;
12
13 overrides?: PartialServiceMap<S>;
14 }
15
16 export class DescriptorImpl<S extends object, T> implements Descriptor<S, T> {
17
18 private readonly _overrides?: PartialServiceMap<S>;
19
20 private readonly _lifetime: ILifetime;
21
22 private readonly _factory: (resolve: Resolver<S>) => T;
23
24 private readonly _cleanup?: (item: T) => void;
25
26 constructor(args: DescriptorImplArgs<S, T>) {
27 this._lifetime = args.lifetime;
28 this._factory = args.factory;
29 if (args.cleanup)
30 this._cleanup = args.cleanup;
31 if (args.overrides)
32 this._overrides = args.overrides;
33 }
34
35 activate(context: ActivationContext<S>): T {
36
37 if (this._lifetime.has())
38 return this._lifetime.get();
39
40 this._lifetime.initialize(context);
41
42 if (this._overrides)
43 each(this._overrides, (v, k) => context.register(k, v));
44
45 const resolve = (name: ContainerKeys<S>, opts?: DependencyOptions | LazyDependencyOptions) => {
46 if (opts && "lazy" in opts && opts.lazy) {
47 const c2 = context.clone();
48 return () => {
49 return opts.optional ? c2.resolve(name, opts.default) : c2.resolve(name);
50 };
51 } else {
52 return opts && opts.optional ? context.resolve(name, opts.default) : context.resolve(name);
53 }
54 };
55
56 const instance = this._factory.call(undefined, resolve);
57
58 this._lifetime.store(instance, this._cleanup);
59
60 return instance;
61 }
62
63 }
@@ -0,0 +1,58
1 import { Container } from "../Container";
2 import { argumentNotNull, each, isPrimitive, isPromise } from "../../safe";
3 import { DescriptorBuilder } from "./DescriptorBuilder";
4 import { RegistrationBuilder, FluentRegistrations } from "./interfaces";
5 import { Cancellation } from "../../Cancellation";
6
7 export class FluentConfiguration<S extends object, Y extends keyof S = keyof S> {
8
9 _builders: { [k in keyof S]?: RegistrationBuilder<S, S[k]> } = {};
10
11 register<K extends Y>(name: K, builder: RegistrationBuilder<S, S[K]>): FluentConfiguration<S, Exclude<Y, K>>;
12 register<K extends Y>(config: FluentRegistrations<K, S>): FluentConfiguration<S, Exclude<Y, K>>;
13 register<K extends Y>(nameOrConfig: K | FluentRegistrations<K, S>, builder?: RegistrationBuilder<S, S[K]>): FluentConfiguration<S, Exclude<Y, K>> {
14 if (isPrimitive(nameOrConfig)) {
15 argumentNotNull(builder, "builder");
16 this._builders[nameOrConfig] = builder;
17 } else {
18 each(nameOrConfig, (v, k) => this.register(k, v));
19 }
20
21 return this;
22 }
23
24 apply(target: Container<S>, ct = Cancellation.none) {
25
26 let pending = 1;
27
28 return new Promise((resolve, reject) => {
29 function guard(v: void | Promise<void>) {
30 if (isPromise(v))
31 v.catch(reject);
32 }
33
34 function complete() {
35 if (!--pending)
36 resolve();
37 }
38 each(this._builders, (v, k) => {
39 pending++;
40 const d = new DescriptorBuilder<S, any>(target,
41 result => {
42 target.register(k, result);
43 complete();
44 },
45 reject
46 );
47
48 try {
49 guard(v(d, ct));
50 } catch (e) {
51 reject(e);
52 }
53 });
54 complete();
55 });
56 }
57
58 }
@@ -0,0 +1,54
1 import { test } from "./TestTraits";
2 import { fluent } from "../di/traits";
3 import { Bar } from "../mock/Bar";
4 import { Container } from "../di/Container";
5 import { Foo } from "../mock/Foo";
6 import { Box } from "../mock/Box";
7 import { delay } from "../safe";
8
9 test("Simple fluent config", async t => {
10 const config = fluent<{ host: string; bar: Bar; foo: Foo }>()
11 .register({
12 host: it => it.value("example.com"),
13 bar: it => it.factory(resolve => new Bar({ host: resolve("host") }, "s-bar")),
14 foo: it => import("../mock/Foo").then(m => it.lifetime("container").factory(() => new m.Foo()))
15 });
16
17 const container = new Container<{ host: string; bar: Bar; foo: Foo; }>();
18 await config.apply(container);
19
20 t.equal(container.resolve("host"), "example.com", "The value should be resolved");
21 t.assert(container.resolve("bar"), "The service should de activated");
22 t.equal(container.resolve("foo"), container.resolve("foo"), "The service should be activated once");
23 });
24
25 test("Nested async configuration", async t => {
26 const container = await new Container<{
27 foo: Foo;
28 box: Box<Foo>
29 }>().fluent({
30 foo: it => delay(0).then(() => it.factory(() => new Foo())),
31 box: it => it.lifetime("context").factory($dependency => new Box($dependency("foo")))
32 });
33
34 t.assert(container.resolve("box").getValue(), "The dependency should be set");
35 t.equals(container.resolve("box").getValue(), container.resolve("box").getValue(), "The service should be activated once")
36 });
37
38 test("Bad fluent config", async t => {
39 try {
40 await new Container<{
41 foo: Foo;
42 box: Box<Foo>
43 }>().fluent({
44 foo: it => delay(0).then(() => it.factory(() => new Foo())),
45 box: it => it.lifetime("context")
46 .override("foo", () => { throw new Error("bad override"); })
47 .factory($dependency => new Box($dependency("foo")))
48 });
49 t.fail("Should throw");
50 } catch (e) {
51 t.pass("The configuration should fail");
52 t.equal(e.message, "bad override", "the error should pass");
53 }
54 });
@@ -15,6 +15,10 export interface ActivationContextInfo {
15 15
16 16 let nextId = 1;
17 17
18 /** This class is created once per `Container.resolve` method call and used to
19 * cache dependencies and to track created instances. The activation context
20 * tracks services with `context` activation type.
21 */
18 22 export class ActivationContext<S extends object> {
19 23 _cache: MapOf<any>;
20 24
@@ -30,6 +34,14 export class ActivationContext<S extends
30 34
31 35 _parent: ActivationContext<S> | undefined;
32 36
37 /** Creates a new activation context with the specified parameters.
38 * @param container the container which starts the activation process
39 * @param services the initial service registrations
40 * @param name the name of the service being activated, this parameter is
41 * used for the debug purpose.
42 * @param service the service to activate, this parameter is used for the
43 * debug purpose.
44 */
33 45 constructor(container: Container<S>, services: ContainerServiceMap<S>, name: string, service: Descriptor<S, any>) {
34 46 this._name = name;
35 47 this._service = service;
@@ -39,16 +51,33 export class ActivationContext<S extends
39 51 this._container = container;
40 52 }
41 53
54 /** the name of the current resolving dependency */
42 55 getName() {
43 56 return this._name;
44 57 }
45 58
59 /** Returns the container for which 'resolve' method was called */
46 60 getContainer() {
47 61 return this._container;
48 62 }
49 63
64 /** Resolves the specified dependency in the current context
65 * @param name The name of the dependency being resolved
66 */
50 67 resolve<K extends ContainerKeys<S>>(name: K): TypeOfService<S, K>;
68 /** Resolves the specified dependency with the specified default value if
69 * the dependency is missing.
70 *
71 * @param name The name of the dependency being resolved
72 * @param def A default value to return in case of the specified dependency
73 * is missing.
74 */
51 75 resolve<K extends ContainerKeys<S>, T>(name: K, def: T): TypeOfService<S, K> | T;
76 /** Resolves the specified dependency and returns undefined in case if the
77 * dependency is missing.
78 *
79 * @param name The name of the dependency being resolved
80 */
52 81 resolve<K extends ContainerKeys<S>>(name: K, def: undefined): TypeOfService<S, K> | undefined;
53 82 resolve<K extends ContainerKeys<S>, T>(name: K, def?: T): TypeOfService<S, K> | T | undefined {
54 83 const d = this._services[name];
@@ -92,6 +121,7 export class ActivationContext<S extends
92 121 }
93 122 };
94 123 }
124
95 125 activate<T>(d: Descriptor<S, T>, name: string) {
96 126 if (trace.isLogEnabled())
97 127 trace.log(`enter ${name} ${d}`);
@@ -1,7 +1,7
1 1 import { ActivationContext } from "./ActivationContext";
2 2 import { ValueDescriptor } from "./ValueDescriptor";
3 3 import { ActivationError } from "./ActivationError";
4 import { ServiceMap, Descriptor, PartialServiceMap, ContainerProvided, ServiceLocator, ContainerServiceMap, ContainerKeys, TypeOfService, ILifetimeManager } from "./interfaces";
4 import { ServiceMap, Descriptor, PartialServiceMap, ServiceLocator, ContainerServiceMap, ContainerKeys, TypeOfService } from "./interfaces";
5 5 import { TraceSource } from "../log/TraceSource";
6 6 import { Configuration, RegistrationMap } from "./Configuration";
7 7 import { Cancellation } from "../Cancellation";
@@ -9,13 +9,15 import { MapOf, IDestroyable } from "../
9 9 import { isDescriptor } from "./traits";
10 10 import { LifetimeManager } from "./LifetimeManager";
11 11 import { each } from "../safe";
12 import { FluentRegistrations } from "./fluent/interfaces";
13 import { FluentConfiguration } from "./fluent/FluentConfiguration";
12 14
13 15 const trace = TraceSource.get("@implab/core/di/ActivationContext");
14 16
15 17 export class Container<S extends object = any> implements ServiceLocator<S>, IDestroyable {
16 18 readonly _services: ContainerServiceMap<S>;
17 19
18 readonly _lifetimeManager: ILifetimeManager;
20 readonly _lifetimeManager: LifetimeManager;
19 21
20 22 readonly _cleanup: (() => void)[];
21 23
@@ -126,6 +128,11 export class Container<S extends object
126 128 }
127 129 }
128 130
131 async fluent<K extends keyof S>(config: FluentRegistrations<K, S>, ct = Cancellation.none): Promise<this> {
132 await new FluentConfiguration<S>().register(config).apply(this, ct);
133 return this;
134 }
135
129 136 createChildContainer<S2 extends object = S>(): Container<S & S2> {
130 137 return new Container<S & S2>(this as any);
131 138 }
@@ -1,6 +1,6
1 1 import { IDestroyable, MapOf } from "../interfaces";
2 import { argumentNotNull, isDestroyable } from "../safe";
3 import { ILifetimeManager, ILifetime } from "./interfaces";
2 import { argumentNotNull, isDestroyable, primitive, isNull, argumentNotEmptyString } from "../safe";
3 import { ILifetime } from "./interfaces";
4 4 import { ActivationContext } from "./ActivationContext";
5 5 import { Container } from "./Container";
6 6
@@ -12,7 +12,7 function safeCall(item: () => void) {
12 12 }
13 13 }
14 14
15 const emptyLifetime: ILifetime = {
15 const emptyLifetime: ILifetime = Object.freeze({
16 16 has() {
17 17 return false;
18 18 },
@@ -29,11 +29,11 const emptyLifetime: ILifetime = {
29 29 // does nothing
30 30 }
31 31
32 };
32 });
33 33
34 const unknownLifetime: ILifetime = {
34 const unknownLifetime: ILifetime = Object.freeze({
35 35 has() {
36 throw new Error("The lifetime is unknown");
36 return false;
37 37 },
38 38 initialize() {
39 39 throw new Error("Can't call initialize on the unknown lifetime object");
@@ -44,11 +44,13 const unknownLifetime: ILifetime = {
44 44 store() {
45 45 throw new Error("Can't store a value in the unknown lifetime object");
46 46 }
47 }
47 });
48 48
49 49 let nextId = 0;
50 50
51 export class LifetimeManager implements IDestroyable, ILifetimeManager {
51 const singletons: { [k in keyof any]: any; } = {};
52
53 export class LifetimeManager implements IDestroyable {
52 54 private _cleanup: (() => void)[] = [];
53 55 private _cache: MapOf<any> = {};
54 56 private _destroyed = false;
@@ -116,7 +118,7 export class LifetimeManager implements
116 118 if (_lifetime !== unknownLifetime)
117 119 throw new Error("Cyclic reference activation detected");
118 120
119 _lifetime = context.getContainer().getLifetimeManager().create(context);
121 _lifetime = context.getContainer().getLifetimeManager().create();
120 122 },
121 123 get() {
122 124 return _lifetime.get();
@@ -151,7 +153,27 export class LifetimeManager implements
151 153 }
152 154
153 155 static singletonLifetime(typeId: string): ILifetime {
154 return emptyLifetime;
156 argumentNotEmptyString(typeId, "typeId");
157 let pending = false;
158 return {
159 has() {
160 return typeId in singletons;
161 },
162 get() {
163 if (!this.has())
164 throw new Error(`The instance ${typeId} doesn't exists`);
165 return singletons[typeId];
166 },
167 initialize() {
168 if (pending)
169 throw new Error("Cyclic reference detected");
170 pending = true;
171 },
172 store(item: any) {
173 singletons[typeId] = item;
174 pending = false;
175 }
176 };
155 177 }
156 178
157 179 static containerLifetime(container: Container<any>) {
@@ -160,7 +182,7 export class LifetimeManager implements
160 182 initialize(context: ActivationContext<any>) {
161 183 if (_lifetime !== unknownLifetime)
162 184 throw new Error("Cyclic reference detected");
163 _lifetime = container.getLifetimeManager().create(context);
185 _lifetime = container.getLifetimeManager().create();
164 186 },
165 187 get() {
166 188 return _lifetime.get();
@@ -1,5 +1,5
1 1 import { ActivationContext } from "./ActivationContext";
2 import { Descriptor, ServiceMap, PartialServiceMap, ILifetimeManager, ILifetime } from "./interfaces";
2 import { Descriptor, ServiceMap, PartialServiceMap, ILifetime } from "./interfaces";
3 3 import { isPrimitive, keys, isNull } from "../safe";
4 4 import { TraceSource } from "../log/TraceSource";
5 5 import { isDescriptor } from "./traits";
@@ -1,46 +1,94
1 import { Resolver, LazyDependencyOptions, DependencyOptions } from "./interfaces";
1 import { Resolver, RegistrationBuilder } from "./interfaces";
2 2 import { Container } from "../Container";
3 import { Descriptor, ILifetime, ContainerKeys } from "../interfaces";
4 import { ActivationContext } from "../ActivationContext";
3 import { Descriptor, ILifetime, ActivationType, PartialServiceMap } from "../interfaces";
4 import { DescriptorImpl } from "./DescriptorImpl";
5 import { LifetimeManager } from "../LifetimeManager";
6 import { isString, each, isPrimitive, isPromise, oid } from "../../safe";
7
8 export class DescriptorBuilder<S extends object, T> {
9 private readonly _container: Container<S>;
10 private readonly _cb: (d: Descriptor<S, T>) => void;
11
12 private readonly _eb: (err: any) => void;
5 13
6 export class DescriptorBuilder<T, S extends object> {
7 readonly _container: Container<S>;
8 readonly _cb: (d: Descriptor<S, T>) => void;
14 private _lifetime = LifetimeManager.empty();
15
16 private _overrides?: PartialServiceMap<S>;
17
18 private _cleanup?: (item: T) => void;
9 19
10 constructor(container: Container<S>, cb: (d: Descriptor<S, T>) => void) {
20 private _factory?: (resolve: Resolver<S>) => T;
21
22 private _pending = 1;
23
24 private _failed = false;
25
26 constructor(container: Container<S>, cb: (d: Descriptor<S, T>) => void, eb: (err: any) => void) {
11 27 this._container = container;
12 28 this._cb = cb;
29 this._eb = eb;
30 }
31
32 build<T2>(): DescriptorBuilder<S, T2> {
33 this._defer();
34 return new DescriptorBuilder<S, T2>(this._container, () => this._complete(), err => this._fail(err));
13 35 }
14 36
15 factory(f: (resolve: Resolver<S>, activate: (lifetime: ILifetime, factory: () => any, cleanup?: (item: any) => void) => any) => T): void {
16 this._cb({
17 activate(context: ActivationContext<S>) {
18 const resolve = (name: ContainerKeys<S>, opts?: DependencyOptions | LazyDependencyOptions) => {
19 if (opts && "lazy" in opts && opts.lazy) {
20 const c2 = context.clone();
21 return () => {
22 return opts.optional ? c2.resolve(name, opts.default) : c2.resolve(name);
23 };
24 } else {
25 return opts && opts.optional ? context.resolve(name, opts.default) : context.resolve(name);
26 }
27 };
37 override<K extends keyof S>(name: K, builder: RegistrationBuilder<S, S[K]>): this;
38 override<K extends keyof S>(services: { [name in K]: RegistrationBuilder<S, S[K]> }): this;
39 override<K extends keyof S>(nameOrServices: K | { [name in K]: RegistrationBuilder<S, S[K]> }, builder?: RegistrationBuilder<S, S[K]>): this {
40 const overrides: PartialServiceMap<S> = this._overrides ?
41 this._overrides :
42 (this._overrides = {});
43
44 const guard = (v: void | Promise<void>) => {
45 if (isPromise(v))
46 v.catch(err => this._fail(err));
47 };
48
49 if (isPrimitive(nameOrServices)) {
50 if (builder) {
51 this._defer();
52 const d = new DescriptorBuilder<S, S[K]>(
53 this._container,
54 result => {
55 overrides[nameOrServices] = result;
56 this._complete();
57 },
58 err => this._fail(err)
59 );
28 60
29 const activate = (lifetime: ILifetime, factory: () => any, cleanup?: (item: any) => void) => {
30 if (lifetime.has()) {
31 return lifetime.get();
32 } else {
33 lifetime.initialize(context);
34 const instance = factory();
35 lifetime.store(instance, cleanup);
36 return instance;
37 }
61 try {
62 guard(builder(d));
63 } catch (err) {
64 this._fail(err);
65 }
66 }
67 } else {
68 each(nameOrServices, (v, k) => this.override(k, v));
69 }
70 return this;
71 }
38 72
39 };
73 lifetime(lifetime: "singleton", typeId: string): this;
74 lifetime(lifetime: ILifetime | Exclude<ActivationType, "singleton">): this;
75 lifetime(lifetime: ILifetime | ActivationType, typeId?: string): this {
76 if (isString(lifetime)) {
77 this._lifetime = this._resolveLifetime(lifetime, typeId);
78 } else {
79 this._lifetime = lifetime;
80 }
81 return this;
82 }
40 83
41 return f(resolve, activate);
42 }
43 });
84 cleanup(cb: (item: T) => void): this {
85 this._cleanup = cb;
86 return this;
87 }
88
89 factory(f: (resolve: Resolver<S>) => T): void {
90 this._factory = f;
91 this._complete();
44 92 }
45 93
46 94 value(v: T): void {
@@ -51,4 +99,49 export class DescriptorBuilder<T, S exte
51 99 });
52 100 }
53 101
102 _resolveLifetime(activation: ActivationType, typeId?: string | object) {
103 switch (activation) {
104 case "container":
105 return LifetimeManager.containerLifetime(this._container);
106 case "hierarchy":
107 return LifetimeManager.hierarchyLifetime();
108 case "context":
109 return LifetimeManager.contextLifetime();
110 case "singleton":
111 if (!typeId)
112 throw Error("The singleton activation requires a typeId");
113
114 const _oid = isString(typeId) ? typeId : oid(typeId);
115
116 return LifetimeManager.singletonLifetime(_oid);
117 default:
118 return LifetimeManager.empty();
119 }
120 }
121
122 _defer() {
123 this._pending++;
124 }
125
126 _complete() {
127 if (--this._pending === 0) {
128 if (!this._factory)
129 throw new Error("The factory must be specified");
130
131 this._cb(new DescriptorImpl<S, T>({
132 lifetime: this._lifetime,
133 factory: this._factory,
134 overrides: this._overrides,
135 cleanup: this._cleanup
136 }));
137 }
138 }
139
140 _fail(err: any) {
141 if (!this._failed) {
142 this._failed = true;
143 this._eb.call(undefined, err);
144 }
145 }
146
54 147 }
@@ -1,6 +1,6
1 1 import { primitive } from "../../safe";
2 import { AnnotationBuilder } from "../Annotations";
3 import { ILifetime, TypeOfService, ContainerKeys } from "../interfaces";
2 import { TypeOfService, ContainerKeys, ActivationType, ILifetime } from "../interfaces";
3 import { ICancellation } from "../../interfaces";
4 4
5 5 export interface DependencyOptions {
6 6 optional?: boolean;
@@ -22,10 +22,6 export type ExtractDependency<D, S> = D
22 22 export type WalkDependencies<D, S> = D extends primitive ? D :
23 23 { [K in keyof D]: ExtractDependency<D[K], S> };
24 24
25 export type ServiceModule<T, S extends object, M extends keyof any = "service"> = {
26 [m in M]: AnnotationBuilder<T, S>;
27 };
28
29 25 export type InferReferenceType<S extends object, K extends ContainerKeys<S>, O> = O extends { default: infer X } ? (TypeOfService<S, K> | X) :
30 26 O extends { optional: true } ? (TypeOfService<S, K> | undefined) :
31 27 TypeOfService<S, K>;
@@ -35,14 +31,22 export interface Resolver<S extends obje
35 31 <K extends ContainerKeys<S>, O extends DependencyOptions>(this: void, name: K, opts?: O): InferReferenceType<S, K, O>;
36 32 }
37 33
38 export interface DescriptorBuilder<T, S extends object> {
39 service(service: AnnotationBuilder<T, S> | ServiceModule<T, S>): void;
34 export interface DescriptorBuilder<S extends object, T> {
35 factory(f: (resolve: Resolver<S>) => T): void;
36
37 build<T2>(): DescriptorBuilder<S, T2>;
40 38
41 factory(f: (resolve: Resolver<S>, activate: <T2>(lifetime: ILifetime, factory: () => T2, cleanup?: (item: T2) => void) => T2) => T): void;
39 override<K extends keyof S>(name: K, builder: RegistrationBuilder<S, S[K]>): this;
40 override<K extends keyof S>(services: { [name in K]: RegistrationBuilder<S, S[K]> }): this;
41
42 lifetime(lifetime: "singleton", typeId: any): this;
43 lifetime(lifetime: ILifetime | Exclude<ActivationType, "singleton">): this;
44
45 cleanup(cb: (item: T) => void): this;
42 46
43 47 value(v: T): void;
44 48 }
45 49
46 export interface Configuration<S extends object, Y extends keyof S = keyof S> {
47 register<K extends Y>(name: K, builder: (d: DescriptorBuilder<S[K], S>) => void): Configuration<S, Exclude<Y, K>>;
48 }
50 export type RegistrationBuilder<S extends object, T> = (d: DescriptorBuilder<S, T>, ct?: ICancellation) => void | Promise<void>;
51
52 export type FluentRegistrations<K extends keyof S, S extends object> = { [k in K]: RegistrationBuilder<S, S[k]> };
@@ -37,10 +37,6 export type ContainerRegistered<S extend
37 37
38 38 export type ActivationType = "singleton" | "container" | "hierarchy" | "context" | "call";
39 39
40 export interface ILifetimeManager {
41 create(context: ActivationContext<any>): ILifetime;
42 }
43
44 40 /**
45 41 * Интерфейс для управления жизнью экземпляра объекта. Каждая регистрация имеет
46 42 * свой собственный объект `ILifetime`, который создается при первой активации
@@ -1,12 +1,11
1 1 import { isPrimitive } from "../safe";
2 2 import { Descriptor } from "./interfaces";
3 import { Configuration } from "./fluent/Configuration";
4
3 import { FluentConfiguration } from "./fluent/FluentConfiguration";
5 4 export function isDescriptor(x: any): x is Descriptor {
6 5 return (!isPrimitive(x)) &&
7 6 (x.activate instanceof Function);
8 7 }
9 8
10 export function configure<S extends object>() {
11 return new Configuration<S>();
9 export function fluent<S extends object>() {
10 return new FluentConfiguration<S>();
12 11 }
@@ -1,4 +1,4
1 import { ICancellable, Constructor, IDestroyable } from "./interfaces";
1 import { ICancellable, Constructor, IDestroyable, PromiseOrValue } from "./interfaces";
2 2 import { Cancellation } from "./Cancellation";
3 3
4 4 let _nextOid = 0;
@@ -6,6 +6,8 const _oid = typeof Symbol === "function
6 6 Symbol("__implab__oid__") :
7 7 "__implab__oid__";
8 8
9 export function oid(instance: null | undefined): undefined;
10 export function oid(instance: NonNullable<any>): string;
9 11 export function oid(instance: any): string | undefined {
10 12 if (isNull(instance))
11 13 return undefined;
@@ -1,16 +1,19
1 1 import { Services } from "./services";
2 import { configure } from "../di/traits";
3 import { LifetimeManager } from "../di/LifetimeManager";
2 import { fluent } from "../di/traits";
3
4 export default fluent<Services>().register({
5 host: it => it.value("example.com"),
4 6
5 export const config = configure<Services>()
6 .register("host", s => s.value("example.com"))
7 .register("bar2", bar2 => Promise.all([import("./Foo"), import("./Bar")])
8 .then(([{ Foo }, { Bar }]) => {
9 const lifetime = LifetimeManager.hierarchyLifetime();
10
11 bar2.factory((resolve, activate) => {
7 bar2: it => Promise.all([import("./Foo"), import("./Bar")])
8 .then(([{ Foo }, { Bar }]) => it
9 .lifetime("container")
10 .override({
11 host: it2 => it2.value("simple.org"),
12 foo: it2 => it2.value(new Foo())
13 })
14 .factory(resolve => {
12 15 const bar = new Bar({
13 foo: activate(lifetime, () => new Foo()),
16 foo: new Foo(),
14 17 nested: {
15 18 lazy: resolve("foo", { lazy: true })
16 19 },
@@ -18,6 +21,6 export const config = configure<Services
18 21 }, "some text");
19 22 bar.setName(resolve("host"));
20 23 return bar;
21 });
22 })
23 );
24 })
25 )
26 });
@@ -6,7 +6,6 import { ValueDescriptor } from "../di/V
6 6 import { Foo } from "../mock/Foo";
7 7 import { Bar } from "../mock/Bar";
8 8 import { isNull } from "../safe";
9 import { Box } from "ts/mock/Box";
10 9
11 10 test("Container register/resolve tests", async t => {
12 11 const container = new Container<{
@@ -1,8 +1,6
1 1 {
2 2 "extends": "../tsconfig",
3 3 "compilerOptions": {
4 //"rootDir": "ts",
5 "baseUrl": ".",
6 4 "rootDirs": [
7 5 "ts",
8 6 "../main/ts"
@@ -6,5 +6,6 define([
6 6 "./ObservableTests",
7 7 "./ContainerTests",
8 8 "./SafeTests",
9 "./TextTests"
9 "./TextTests",
10 "./FluentContainerTests"
10 11 ]); No newline at end of file
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now