Skip to content

Commit ddd6878

Browse files
authored
Add the inject() function (#60)
1 parent 45f3e35 commit ddd6878

4 files changed

+65
-2
lines changed

lib/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,4 @@ export { InjectionToken, OpaqueToken } from './injection_token';
2525
export { Class, TypeDecorator, makeDecorator, makeParamDecorator, makePropDecorator } from './util/decorators';
2626
export { resolveDependencies } from './util/resolve_dependencies';
2727
export { Type, isType } from './facade/type';
28+
export { inject } from './injector_compatibility';

lib/injector_compatibility.ts

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { Type } from "./facade/type";
2+
import { InjectionToken } from "./injection_token";
3+
import { Injector } from "./injector";
4+
5+
6+
/**
7+
* Current injector value used by `inject`.
8+
* - `undefined`: it is an error to call `inject`
9+
* - Injector instance: Use the injector for resolution.
10+
*/
11+
let _currentInjector: Injector | undefined = undefined;
12+
13+
export function getCurrentInjector(): Injector | undefined {
14+
return _currentInjector;
15+
}
16+
17+
18+
export function setCurrentInjector(
19+
injector: Injector | undefined,
20+
): Injector | undefined {
21+
const former = _currentInjector;
22+
_currentInjector = injector;
23+
return former;
24+
}
25+
26+
27+
export function inject<T>(token: Type<T> | InjectionToken<T>): T {
28+
if (_currentInjector === undefined) {
29+
throw new Error(
30+
`inject() must be called from an injection context such as a constructor, a factory function, or a field initializer`,
31+
);
32+
} else {
33+
const value = _currentInjector.get(token);
34+
return value;
35+
}
36+
}

lib/reflective_injector.ts

+13-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9+
import { Type } from './facade/type';
910
import { Injector, THROW_IF_NOT_FOUND } from './injector';
11+
import { setCurrentInjector } from './injector_compatibility';
1012
import { Self, SkipSelf } from './metadata';
1113
import { Provider } from './provider';
1214
import { cyclicDependencyError, instantiationError, noProviderError, outOfBoundsError } from './reflective_errors';
@@ -333,7 +335,7 @@ export class ReflectiveInjector_ implements ReflectiveInjector {
333335
}
334336

335337
instantiateResolved(provider: ResolvedReflectiveProvider): any {
336-
return this._instantiateProvider(provider);
338+
return this._instantiateProviderContext(provider);
337339
}
338340

339341
getProviderAtIndex(index: number): ResolvedReflectiveProvider {
@@ -348,13 +350,22 @@ export class ReflectiveInjector_ implements ReflectiveInjector {
348350
if (this._constructionCounter++ > this._getMaxNumberOfObjects()) {
349351
throw cyclicDependencyError(this, provider.key);
350352
}
351-
return this._instantiateProvider(provider);
353+
return this._instantiateProviderContext(provider);
352354
}
353355

354356
private _getMaxNumberOfObjects(): number {
355357
return this.objs.length;
356358
}
357359

360+
private _instantiateProviderContext(provider: ResolvedReflectiveProvider): any {
361+
const previousInjector = setCurrentInjector(this);
362+
try {
363+
return this._instantiateProvider(provider);
364+
} finally {
365+
setCurrentInjector(previousInjector);
366+
}
367+
}
368+
358369
private _instantiateProvider(provider: ResolvedReflectiveProvider): any {
359370
if (provider.multiProvider) {
360371
const res = new Array(provider.resolvedFactories.length);

test/reflective_injector_spec.ts

+15
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
ReflectiveKey,
2020
Self,
2121
forwardRef,
22+
inject,
2223
} from '../lib';
2324
import { ReflectiveInjector_ } from '../lib/reflective_injector';
2425
import { ResolvedReflectiveProvider_ } from '../lib/reflective_provider';
@@ -41,6 +42,13 @@ class Dashboard {
4142
constructor(software: DashboardSoftware) {}
4243
}
4344

45+
class GloveboxManual {}
46+
47+
@Injectable()
48+
class Glovebox {
49+
manual = inject(GloveboxManual);
50+
}
51+
4452
class TurboEngine extends Engine {}
4553

4654
@Injectable()
@@ -351,6 +359,13 @@ describe(`injector`, () => {
351359
const injector = createInjector([{ provide: 'null', useValue: null }]);
352360
expect(injector.get('null')).toBe(null);
353361
});
362+
363+
it('should support the inject() function', () => {
364+
const injector = createInjector([Glovebox, GloveboxManual]);
365+
const glovebox = injector.get(Glovebox);
366+
expect(glovebox instanceof Glovebox).toBe(true);
367+
expect(glovebox.manual instanceof GloveboxManual).toBe(true);
368+
});
354369
});
355370

356371
describe('child', () => {

0 commit comments

Comments
 (0)