Skip to content

Commit 9d5918e

Browse files
committed
refactor(core): add MapInjector.createFactory and add factories to MapInjector.
This makes `InjectorFactory` a general concept that can be used without codegen as well. Closes angular#9370
1 parent ca27cc4 commit 9d5918e

13 files changed

Lines changed: 160 additions & 61 deletions

File tree

modules/angular2/src/compiler/identifiers.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import {QueryList} from 'angular2/src/core/linker';
2626
import {Injector} from 'angular2/src/core/di/injector';
2727
import {TemplateRef, TemplateRef_} from 'angular2/src/core/linker/template_ref';
2828
import {MODULE_SUFFIX} from './util';
29-
import {CodegenInjector, InjectorFactory} from 'angular2/src/core/linker/injector_factory';
29+
import {CodegenInjector, CodegenInjectorFactory} from 'angular2/src/core/linker/injector_factory';
3030

3131
var APP_VIEW_MODULE_URL = 'asset:angular2/lib/src/core/linker/view' + MODULE_SUFFIX;
3232
var VIEW_UTILS_MODULE_URL = 'asset:angular2/lib/src/core/linker/view_utils' + MODULE_SUFFIX;
@@ -50,7 +50,7 @@ var impTemplateRef_ = TemplateRef_;
5050
var impValueUnwrapper = ValueUnwrapper;
5151
var impInjector = Injector;
5252
var impCodegenInjector = CodegenInjector;
53-
var impInjectorFactory = InjectorFactory;
53+
var impCodegenInjectorFactory = CodegenInjectorFactory;
5454
var impViewEncapsulation = ViewEncapsulation;
5555
var impViewType = ViewType;
5656
var impChangeDetectionStrategy = ChangeDetectionStrategy;
@@ -122,9 +122,9 @@ export class Identifiers {
122122
runtime: impInjector
123123
});
124124
static InjectorFactory = new CompileIdentifierMetadata({
125-
name: 'InjectorFactory',
125+
name: 'CodegenInjectorFactory',
126126
moduleUrl: `asset:angular2/lib/src/core/linker/injector_factory${MODULE_SUFFIX}`,
127-
runtime: impInjectorFactory
127+
runtime: impCodegenInjectorFactory
128128
});
129129
static CodegenInjector = new CompileIdentifierMetadata({
130130
name: 'CodegenInjector',

modules/angular2/src/compiler/runtime_compiler.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ import {TemplateParser} from './template_parser';
5050
import {DirectiveNormalizer} from './directive_normalizer';
5151
import {RuntimeMetadataResolver} from './runtime_metadata';
5252
import {ComponentFactory} from 'angular2/src/core/linker/component_factory';
53-
import {InjectorFactory} from 'angular2/src/core/linker/injector_factory';
53+
import {CodegenInjectorFactory} from 'angular2/src/core/linker/injector_factory';
5454
import {
5555
ComponentResolver,
5656
ReflectorComponentResolver
@@ -83,7 +83,7 @@ export class RuntimeCompiler implements ComponentResolver {
8383
private _injectorCompiler: InjectorCompiler, private _genConfig: CompilerConfig) {}
8484

8585
createInjectorFactory(moduleClass: Type,
86-
extraProviders: any[] = CONST_EXPR([])): InjectorFactory<any> {
86+
extraProviders: any[] = CONST_EXPR([])): CodegenInjectorFactory<any> {
8787
var injectorModuleMeta =
8888
this._runtimeMetadataResolver.getInjectorModuleMetadata(moduleClass, extraProviders);
8989
var compileResult = this._injectorCompiler.compileInjector(injectorModuleMeta);

modules/angular2/src/core/di.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export * from './di/decorators';
1919

2020
export {forwardRef, resolveForwardRef, ForwardRefFn} from './di/forward_ref';
2121

22-
export {Injector, MapInjector} from './di/injector';
22+
export {Injector, InjectorFactory} from './di/injector';
2323
export {ReflectiveInjector} from './di/reflective_injector';
2424
export {
2525
Binding,
@@ -47,3 +47,4 @@ export {
4747
OutOfBoundsError
4848
} from './di/reflective_exceptions';
4949
export {OpaqueToken} from './di/opaque_token';
50+
export {MapInjector, MapInjectorFactory} from './di/map_injector';

modules/angular2/src/core/di/injector.ts

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -48,20 +48,18 @@ export abstract class Injector {
4848
get(token: any, notFoundValue?: any): any { return unimplemented(); }
4949
}
5050

51+
class _EmptyInjectorFactory implements InjectorFactory<any> {
52+
create(parent: Injector = null, context: any = null): Injector {
53+
return isBlank(parent) ? Injector.NULL : parent;
54+
}
55+
}
56+
5157
/**
52-
* An simple injector based on a Map of values.
58+
* A factory for an injector.
5359
*/
54-
export class MapInjector implements Injector {
55-
constructor(private _parent: Injector, private _values: Map<any, any>) {
56-
if (isBlank(this._parent)) {
57-
this._parent = Injector.NULL;
58-
}
59-
}
60-
get(token: any, notFoundValue: any = _THROW_IF_NOT_FOUND): any {
61-
if (token === Injector) {
62-
return this;
63-
}
64-
return this._values.has(token) ? this._values.get(token) :
65-
this._parent.get(token, notFoundValue);
66-
}
60+
export abstract class InjectorFactory<CONTEXT> {
61+
// An InjectorFactory that will always delegate to the parent.
62+
static EMPTY: InjectorFactory<any> = new _EmptyInjectorFactory();
63+
64+
abstract create(parent?: Injector, context?: CONTEXT): Injector;
6765
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import {isBlank} from 'angular2/src/facade/lang';
2+
import {Injector, InjectorFactory, THROW_IF_NOT_FOUND} from './injector';
3+
4+
/**
5+
* An simple injector based on a Map of values.
6+
*/
7+
export class MapInjector implements Injector {
8+
static createFactory(values?: Map<any, any>,
9+
factories?: Map<any, (injector: Injector) => any>): InjectorFactory<any> {
10+
return new MapInjectorFactory(values, factories);
11+
}
12+
13+
private _instances: Map<any, any> = new Map<any, any>();
14+
private _factories: Map<any, (injector: Injector) => any>;
15+
private _values: Map<any, any>;
16+
17+
constructor(private _parent: Injector = null, values: Map<any, any> = null,
18+
factories: Map<any, (injector: Injector) => any> = null) {
19+
if (isBlank(values)) {
20+
values = new Map<any, any>();
21+
}
22+
this._values = values;
23+
if (isBlank(factories)) {
24+
factories = new Map<any, any>();
25+
}
26+
this._factories = factories;
27+
if (isBlank(this._parent)) {
28+
this._parent = Injector.NULL;
29+
}
30+
}
31+
get(token: any, notFoundValue: any = THROW_IF_NOT_FOUND): any {
32+
if (token === Injector) {
33+
return this;
34+
}
35+
if (this._values.has(token)) {
36+
return this._values.get(token);
37+
}
38+
if (this._instances.has(token)) {
39+
return this._instances.get(token);
40+
}
41+
if (this._factories.has(token)) {
42+
var instance = this._factories.get(token)(this);
43+
this._instances.set(token, instance);
44+
return instance;
45+
}
46+
return this._parent.get(token, notFoundValue);
47+
}
48+
}
49+
50+
/**
51+
* InjectorFactory for MapInjector.
52+
*/
53+
export class MapInjectorFactory implements InjectorFactory<any> {
54+
constructor(private _values: Map<any, any> = null,
55+
private _factories: Map<any, (injector: Injector) => any> = null) {}
56+
57+
create(parent: Injector = null, context: any = null): Injector {
58+
return new MapInjector(parent, this._values, this._factories);
59+
}
60+
}

modules/angular2/src/core/linker.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,3 @@ export {EmbeddedViewRef, ViewRef} from './linker/view_ref';
88
export {ViewContainerRef} from './linker/view_container_ref';
99
export {ComponentRef, ComponentFactory} from './linker/component_factory';
1010
export {ExpressionChangedAfterItHasBeenCheckedException} from './linker/exceptions';
11-
export {InjectorFactory} from './linker/injector_factory';

modules/angular2/src/core/linker/component_resolver.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {BaseException, unimplemented} from 'angular2/src/facade/exceptions';
44
import {PromiseWrapper} from 'angular2/src/facade/async';
55
import {reflector} from 'angular2/src/core/reflection/reflection';
66
import {ComponentFactory} from './component_factory';
7-
import {InjectorFactory} from './injector_factory';
7+
import {CodegenInjectorFactory} from './injector_factory';
88

99
/**
1010
* Low-level service for loading {@link ComponentFactory}s, which
@@ -13,7 +13,7 @@ import {InjectorFactory} from './injector_factory';
1313
export abstract class ComponentResolver {
1414
abstract resolveComponent(componentType: Type): Promise<ComponentFactory>;
1515
abstract createInjectorFactory(injectorModule: Type,
16-
extraProviders?: any[]): InjectorFactory<any>;
16+
extraProviders?: any[]): CodegenInjectorFactory<any>;
1717
abstract clearCache();
1818
}
1919

@@ -33,7 +33,7 @@ export class ReflectorComponentResolver extends ComponentResolver {
3333
return PromiseWrapper.resolve(componentFactory);
3434
}
3535

36-
createInjectorFactory(injectorModule: Type, extraProviders?: any[]): InjectorFactory<any> {
36+
createInjectorFactory(injectorModule: Type, extraProviders?: any[]): CodegenInjectorFactory<any> {
3737
return unimplemented();
3838
}
3939

modules/angular2/src/core/linker/injector_factory.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export abstract class CodegenInjector<MODULE> implements Injector {
2020
}
2121

2222
@CONST()
23-
export class InjectorFactory<MODULE> {
23+
export class CodegenInjectorFactory<MODULE> {
2424
constructor(private _injectorFactory: (parent: Injector, mainModule: MODULE) => Injector) {}
2525

2626
create(parent: Injector = null, mainModule: MODULE = null): Injector {

modules/angular2/test/core/application_ref_spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ import {
4444
ComponentRef_,
4545
ComponentRef
4646
} from 'angular2/src/core/linker/component_factory';
47-
import {InjectorFactory} from 'angular2/src/core/linker/injector_factory';
47+
import {CodegenInjectorFactory} from 'angular2/src/core/linker/injector_factory';
4848
import {ExceptionHandler} from 'angular2/src/facade/exception_handler';
4949

5050
export function main() {
@@ -169,7 +169,7 @@ class _MockComponentResolver implements ComponentResolver {
169169
return PromiseWrapper.resolve(this._compFactory);
170170
}
171171

172-
createInjectorFactory(injectorModule: Type, extraProviders?: any[]): InjectorFactory<any> {
172+
createInjectorFactory(injectorModule: Type, extraProviders?: any[]): CodegenInjectorFactory<any> {
173173
return unimplemented();
174174
}
175175

Lines changed: 4 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import {describe, ddescribe, it, iit, expect, beforeEach} from 'angular2/testing_internal';
2-
import {Injector, MapInjector} from 'angular2/core';
3-
import {MapWrapper} from 'angular2/src/facade/collection';
2+
import {Injector, InjectorFactory} from 'angular2/core';
43

54
export function main() {
65
describe('Injector.NULL', () => {
@@ -15,32 +14,10 @@ export function main() {
1514
() => { expect(Injector.NULL.get('someToken', 'notFound')).toEqual('notFound'); });
1615
});
1716

18-
describe('MapInjector', () => {
19-
it('should throw if not found', () => {
20-
expect(() => new MapInjector(null, new Map<any, any>()).get('someToken'))
21-
.toThrowError('No provider for someToken!');
22-
});
17+
describe('InjectorFactory.EMPTY', () => {
18+
it('should return Injector.NULL if no parent is given',
19+
() => { expect(InjectorFactory.EMPTY.create()).toBe(Injector.NULL); });
2320

24-
it('should return the default value', () => {
25-
expect(new MapInjector(null, new Map<any, any>()).get('someToken', 'notFound'))
26-
.toEqual('notFound');
27-
});
28-
29-
it('should return a value from the map', () => {
30-
expect(new MapInjector(null, MapWrapper.createFromPairs([['someToken', 'someValue']]))
31-
.get('someToken'))
32-
.toEqual('someValue');
33-
});
34-
35-
it('should return the injector', () => {
36-
var injector = new MapInjector(null, new Map<any, any>());
37-
expect(injector.get(Injector)).toBe(injector);
38-
});
39-
40-
it('should delegate to the parent', () => {
41-
var parent = new MapInjector(null, MapWrapper.createFromPairs([['someToken', 'someValue']]));
42-
expect(new MapInjector(parent, new Map<any, any>()).get('someToken')).toEqual('someValue');
43-
});
4421

4522
});
4623
}

0 commit comments

Comments
 (0)