Skip to content

Commit 08d8ea8

Browse files
authored
feat(reactant-di): add got/gotAll api for DI container (#90)
1 parent b9efa7b commit 08d8ea8

File tree

3 files changed

+87
-7
lines changed

3 files changed

+87
-7
lines changed

packages/reactant-di/src/createContainer.ts

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
/* eslint-disable @typescript-eslint/no-explicit-any */
12
import {
2-
Container,
3+
Container as BaseContainer,
34
MetadataReader,
45
interfaces,
56
ContainerModule,
@@ -93,6 +94,38 @@ function autoDecorateParams(target: object) {
9394
});
9495
}
9596

97+
export class Container extends BaseContainer {
98+
constructor(
99+
options: interfaces.ContainerOptions,
100+
private _serviceIdentifiers: Map<
101+
interfaces.ServiceIdentifier<any>,
102+
interfaces.ServiceIdentifier<any>[]
103+
>
104+
) {
105+
super(options);
106+
}
107+
108+
/**
109+
* get the loaded module
110+
*/
111+
got<T>(serviceIdentifier: interfaces.ServiceIdentifier<T>): T | undefined {
112+
return this._serviceIdentifiers.has(serviceIdentifier)
113+
? this.get(serviceIdentifier)
114+
: undefined;
115+
}
116+
117+
/**
118+
* get loaded modules
119+
*/
120+
gotAll<T>(
121+
serviceIdentifier: interfaces.ServiceIdentifier<T>
122+
): T[] | undefined {
123+
return this._serviceIdentifiers.has(serviceIdentifier)
124+
? this.getAll(serviceIdentifier)
125+
: undefined;
126+
}
127+
}
128+
96129
export function bindModules(container: Container, modules: ModuleOptions[]) {
97130
const provideMeta = getMetadata(METADATA_KEY.provide);
98131
for (const module of modules) {
@@ -157,7 +190,7 @@ export function createContainer({
157190
options,
158191
}: ContainerConfig) {
159192
setModulesDeps(modules);
160-
const container = new Container(options);
193+
const container = new Container(options!, ServiceIdentifiers);
161194
container.applyCustomMetadataReader(new CustomMetadataReader());
162195
bindModules(container, modules);
163196
container.applyMiddleware(createCollector(ServiceIdentifiers));

packages/reactant-di/src/interfaces.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
/* eslint-disable @typescript-eslint/no-explicit-any */
12
import { interfaces, LazyServiceIdentifer } from 'inversify';
23
import { METADATA_KEY } from './constants';
34
import { Optional } from './optional';
5+
import type { Container as IContainer } from './createContainer';
46

57
type PickByKey<T, P extends keyof T> = {
68
[K in Exclude<keyof T, P>]: T[K];
@@ -10,7 +12,7 @@ export type ContainerOptions = PickByKey<
1012
interfaces.ContainerOptions,
1113
'skipBaseClassChecks'
1214
>;
13-
export type Container = interfaces.Container;
15+
export type Container = IContainer;
1416
export type ServiceIdentifier<T> = interfaces.ServiceIdentifier<T>;
1517
export type ServiceIdentifierOrFunc<T> =
1618
| ServiceIdentifier<T>
@@ -20,13 +22,12 @@ export type ServiceIdentifiersMap<T = any> = Map<
2022
ServiceIdentifier<T>,
2123
ServiceIdentifier<T>[]
2224
>;
23-
24-
export type MetadataMap = Map<ServiceIdentifier<any>, Module<any>>;
25-
2625
export interface Module<T> extends Function {
2726
new (...args: any[]): T;
2827
}
2928

29+
export type MetadataMap = Map<ServiceIdentifier<any>, Module<any>>;
30+
3031
export interface DependencyProviderOption {
3132
provide: ServiceIdentifier<any>;
3233
optional: boolean;

packages/reactant-di/test/index.test.ts

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { injectable, createContainer, inject, optional } from '..';
1+
import { injectable, createContainer, inject, optional, multiInject } from '..';
22

33
test('decoration for interface', () => {
44
interface FooInterface {
@@ -162,3 +162,49 @@ test('mix @optional/@inject about inheritance', () => {
162162
expect(bar.foo instanceof Foo).toBeTruthy();
163163
expect(bar.foo1 instanceof Foo1).toBeTruthy();
164164
});
165+
166+
test('Container APIs: got/gotAll', () => {
167+
@injectable()
168+
class Foo {
169+
public get test() {
170+
return 'test';
171+
}
172+
}
173+
174+
@injectable()
175+
class FooBar {}
176+
177+
@injectable()
178+
class FooBar1 {}
179+
180+
@injectable()
181+
class Bar {
182+
constructor(@multiInject(Foo) public foos: Foo[], public fooBar: FooBar) {}
183+
184+
public get length() {
185+
return this.foos.length;
186+
}
187+
}
188+
189+
const ServiceIdentifiers = new Map();
190+
191+
const container = createContainer({
192+
ServiceIdentifiers,
193+
modules: [Foo, Foo, FooBar],
194+
options: {
195+
defaultScope: 'Singleton',
196+
},
197+
});
198+
199+
const bar = container.get(Bar);
200+
const fooBar = container.get(FooBar);
201+
202+
expect(bar.length).toBe(2);
203+
expect(bar.fooBar instanceof FooBar).toBeTruthy();
204+
expect(bar.fooBar).toBe(fooBar);
205+
expect(container.got(FooBar)).toBe(fooBar);
206+
expect(container.gotAll(Foo)!.length).toBe(2);
207+
expect(container.gotAll(Foo)).toEqual(bar.foos);
208+
expect(container.got(FooBar1)).toBeUndefined();
209+
expect(container.gotAll(FooBar1)).toBeUndefined();
210+
});

0 commit comments

Comments
 (0)