##// END OF EJS Templates
Added LazyReferenceDescriptor, removed lazy behaviour from ReferenceDescriptor.
cin -
r122:118478dfa903 ioc ts support
parent child
Show More
@@ -0,0 +1,84
1 import { argumentNotEmptyString, each } from "../safe";
2 import { ActivationContext } from "./ActivationContext";
3 import { Descriptor, PartialServiceMap, ContainerResolve, ContainerKeys } from "./interfaces";
4 import { ActivationError } from "./ActivationError";
5
6 export interface ReferenceDescriptorParams<S extends object, K extends ContainerKeys<S>> {
7 name: K;
8 optional?: boolean;
9 default?: ContainerResolve<S, K>;
10 services?: PartialServiceMap<S>;
11 }
12
13 export class LazyReferenceDescriptor<S extends object = any, K extends ContainerKeys<S> = ContainerKeys<S>>
14 implements Descriptor<S, ((args?: PartialServiceMap<S>) => ContainerResolve<S, K>)> {
15
16 _name: K;
17
18 _optional = false;
19
20 _default: ContainerResolve<S, K> | undefined;
21
22 _services: PartialServiceMap<S>;
23
24 constructor(opts: ReferenceDescriptorParams<S, K>) {
25 argumentNotEmptyString(opts && opts.name, "opts.name");
26 this._name = opts.name;
27 this._optional = !!opts.optional;
28 this._default = opts.default;
29
30 this._services = (opts.services || {}) as PartialServiceMap<S>;
31 }
32
33 activate(context: ActivationContext<S>) {
34 // добавляем сервисы
35 if (this._services) {
36 each(this._services, (v, k) => context.register(k, v));
37 }
38
39 const saved = context.clone();
40
41 return (cfg?: PartialServiceMap<S>) => {
42 // защищаем контекст на случай исключения в процессе
43 // активации
44 const ct = saved.clone();
45 try {
46 if (cfg) {
47 each(cfg, (v, k) => ct.register(k, v));
48 }
49
50 return this._optional ? ct.resolve(this._name, this._default) : ct
51 .resolve(this._name);
52 } catch (error) {
53 throw new ActivationError(this._name.toString(), ct.getStack(), error);
54 }
55 };
56
57 }
58
59 toString() {
60 const opts = [];
61 if (this._optional)
62 opts.push("optional");
63
64 opts.push("lazy");
65
66 const parts = [
67 "@ref "
68 ];
69 if (opts.length) {
70 parts.push("{");
71 parts.push(opts.join());
72 parts.push("} ");
73 }
74
75 parts.push(this._name.toString());
76
77 if (this._default !== undefined && this._default !== null) {
78 parts.push(" = ");
79 parts.push(String(this._default));
80 }
81
82 return parts.join("");
83 }
84 }
@@ -72,6 +72,8 type ServiceModule<T, S extends object,
72 [m in M]: Builder<T, S>;
72 [m in M]: Builder<T, S>;
73 };
73 };
74
74
75 type PromiseOrValue<T> = PromiseLike<T> | T;
76
75 export interface Config<S extends object, Y extends keyof S = keyof S> {
77 export interface Config<S extends object, Y extends keyof S = keyof S> {
76 register<K extends Y>(name: K, builder: Builder<S[K], S>): Config<S, Exclude<Y, K>>;
78 register<K extends Y>(name: K, builder: Builder<S[K], S>): Config<S, Exclude<Y, K>>;
77 register<K extends Y>(name: K, m: Promise<ServiceModule<S[K], S>>): Config<S, Exclude<Y, K>>;
79 register<K extends Y>(name: K, m: Promise<ServiceModule<S[K], S>>): Config<S, Exclude<Y, K>>;
@@ -18,6 +18,7 import { Cancellation } from "../Cancell
18 import { makeResolver } from "./ResolverHelper";
18 import { makeResolver } from "./ResolverHelper";
19 import { ICancellation } from "../interfaces";
19 import { ICancellation } from "../interfaces";
20 import { isDescriptor } from "./traits";
20 import { isDescriptor } from "./traits";
21 import { LazyReferenceDescriptor } from "./LazyReferenceDescriptor";
21
22
22 export interface RegistrationScope<S extends object> {
23 export interface RegistrationScope<S extends object> {
23
24
@@ -357,13 +358,13 export class Configuration<S extends obj
357 async _visitDependencyRegistration<K extends keyof S>(data: DependencyRegistration<S, K>, name: string) {
358 async _visitDependencyRegistration<K extends keyof S>(data: DependencyRegistration<S, K>, name: string) {
358 argumentNotEmptyString(data && data.$dependency, "data.$dependency");
359 argumentNotEmptyString(data && data.$dependency, "data.$dependency");
359 this._enter(name);
360 this._enter(name);
360 const d = new ReferenceDescriptor<S, K>({
361 const options = {
361 name: data.$dependency,
362 name: data.$dependency,
362 lazy: data.lazy,
363 optional: data.optional,
363 optional: data.optional,
364 default: data.default,
364 default: data.default,
365 services: data.services && await this._visitRegistrations(data.services, "services")
365 services: data.services && await this._visitRegistrations(data.services, "services")
366 });
366 };
367 const d = data.lazy ? new LazyReferenceDescriptor<S, K>(options) : new ReferenceDescriptor<S, K>(options);
367 this._leave();
368 this._leave();
368 return d;
369 return d;
369 }
370 }
@@ -1,23 +1,19
1 import { argumentNotEmptyString, each } from "../safe";
1 import { argumentNotEmptyString, each } from "../safe";
2 import { ActivationContext } from "./ActivationContext";
2 import { ActivationContext } from "./ActivationContext";
3 import { Descriptor, PartialServiceMap, ContainerResolve, ContainerKeys } from "./interfaces";
3 import { Descriptor, PartialServiceMap, ContainerResolve, ContainerKeys } from "./interfaces";
4 import { ActivationError } from "./ActivationError";
5
4
6 export interface ReferenceDescriptorParams<S extends object, K extends ContainerKeys<S>> {
5 export interface ReferenceDescriptorParams<S extends object, K extends ContainerKeys<S>> {
7 name: K;
6 name: K;
8 lazy?: boolean;
9 optional?: boolean;
7 optional?: boolean;
10 default?: ContainerResolve<S, K>;
8 default?: ContainerResolve<S, K>;
11 services?: PartialServiceMap<S>;
9 services?: PartialServiceMap<S>;
12 }
10 }
13
11
14 export class ReferenceDescriptor<S extends object = any, K extends ContainerKeys<S> = ContainerKeys<S>>
12 export class ReferenceDescriptor<S extends object = any, K extends ContainerKeys<S> = ContainerKeys<S>>
15 implements Descriptor<S, ContainerResolve<S, K> | ((args?: PartialServiceMap<S>) => ContainerResolve<S, K>)> {
13 implements Descriptor<S, ContainerResolve<S, K>> {
16
14
17 _name: K;
15 _name: K;
18
16
19 _lazy = false;
20
21 _optional = false;
17 _optional = false;
22
18
23 _default: ContainerResolve<S, K> | undefined;
19 _default: ContainerResolve<S, K> | undefined;
@@ -27,7 +23,6 export class ReferenceDescriptor<S exten
27 constructor(opts: ReferenceDescriptorParams<S, K>) {
23 constructor(opts: ReferenceDescriptorParams<S, K>) {
28 argumentNotEmptyString(opts && opts.name, "opts.name");
24 argumentNotEmptyString(opts && opts.name, "opts.name");
29 this._name = opts.name;
25 this._name = opts.name;
30 this._lazy = !!opts.lazy;
31 this._optional = !!opts.optional;
26 this._optional = !!opts.optional;
32 this._default = opts.default;
27 this._default = opts.default;
33
28
@@ -40,39 +35,17 export class ReferenceDescriptor<S exten
40 each(this._services, (v, k) => context.register(k, v));
35 each(this._services, (v, k) => context.register(k, v));
41 }
36 }
42
37
43 if (this._lazy) {
38 const res = this._optional ?
44 const saved = context.clone();
39 context.resolve(this._name, this._default) :
45
40 context.resolve(this._name);
46 return (cfg?: PartialServiceMap<S>) => {
47 // защищаем контекст на случай исключения в процессе
48 // активации
49 const ct = saved.clone();
50 try {
51 if (cfg) {
52 each(cfg, (v, k) => ct.register(k, v));
53 }
54
41
55 return this._optional ? ct.resolve(this._name, this._default) : ct
42 return res;
56 .resolve(this._name);
57 } catch (error) {
58 throw new ActivationError(this._name.toString(), ct.getStack(), error);
59 }
60 };
61 } else {
62 const v = this._optional ?
63 context.resolve(this._name, this._default) :
64 context.resolve(this._name);
65
66 return v;
67 }
68 }
43 }
69
44
70 toString() {
45 toString() {
71 const opts = [];
46 const opts = [];
72 if (this._optional)
47 if (this._optional)
73 opts.push("optional");
48 opts.push("optional");
74 if (this._lazy)
75 opts.push("lazy");
76
49
77 const parts = [
50 const parts = [
78 "@ref "
51 "@ref "
@@ -3,4 +3,4 import { config } from "./services";
3 config()
3 config()
4 .register("bar", import("./Bar"))
4 .register("bar", import("./Bar"))
5 .register("box", import("./Box"), "service");
5 .register("box", import("./Box"), "service");
6 //.register("foo", import("./Foo"), "Foo");
6 // .register("foo", import("./Foo"), "Foo");
General Comments 0
You need to be logged in to leave comments. Login now