feat(di): support type literals in DI
This commit is contained in:
parent
4320859e1b
commit
358a6750ed
|
@ -9,7 +9,7 @@ export * from './src/di/annotations';
|
||||||
export * from './src/di/decorators';
|
export * from './src/di/decorators';
|
||||||
export {Injector} from './src/di/injector';
|
export {Injector} from './src/di/injector';
|
||||||
export {Binding, ResolvedBinding, Dependency, bind} from './src/di/binding';
|
export {Binding, ResolvedBinding, Dependency, bind} from './src/di/binding';
|
||||||
export {Key, KeyRegistry} from './src/di/key';
|
export {Key, KeyRegistry, TypeLiteral} from './src/di/key';
|
||||||
export {
|
export {
|
||||||
NoBindingError,
|
NoBindingError,
|
||||||
AbstractBindingError,
|
AbstractBindingError,
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
import {MapWrapper} from 'angular2/src/facade/collection';
|
import {MapWrapper} from 'angular2/src/facade/collection';
|
||||||
import {stringify} from 'angular2/src/facade/lang';
|
import {stringify, CONST, Type} from 'angular2/src/facade/lang';
|
||||||
|
import {TypeLiteral} from './type_literal';
|
||||||
|
|
||||||
|
export {TypeLiteral} from './type_literal';
|
||||||
|
|
||||||
// TODO: uncoment `int` once https://github.com/angular/angular/issues/1414 is fixed
|
// TODO: uncoment `int` once https://github.com/angular/angular/issues/1414 is fixed
|
||||||
|
|
||||||
|
@ -18,6 +21,10 @@ import {stringify} from 'angular2/src/facade/lang';
|
||||||
export class Key {
|
export class Key {
|
||||||
token: Object;
|
token: Object;
|
||||||
id: number;
|
id: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
constructor(token: Object, id: number) {
|
constructor(token: Object, id: number) {
|
||||||
this.token = token;
|
this.token = token;
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
@ -46,6 +53,13 @@ export class KeyRegistry {
|
||||||
get(token: Object): Key {
|
get(token: Object): Key {
|
||||||
if (token instanceof Key) return token;
|
if (token instanceof Key) return token;
|
||||||
|
|
||||||
|
// TODO: workaround for https://github.com/Microsoft/TypeScript/issues/3123
|
||||||
|
var theToken = token;
|
||||||
|
if (token instanceof TypeLiteral) {
|
||||||
|
theToken = token.type;
|
||||||
|
}
|
||||||
|
token = theToken;
|
||||||
|
|
||||||
if (MapWrapper.contains(this._allKeys, token)) {
|
if (MapWrapper.contains(this._allKeys, token)) {
|
||||||
return MapWrapper.get(this._allKeys, token);
|
return MapWrapper.get(this._allKeys, token);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
library angular2.di.type_literal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use type literals as DI keys corresponding to generic types.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* Injector.resolveAndCreate([
|
||||||
|
* bind(new TypeLiteral<List<int>>()).toValue([1, 2, 3])
|
||||||
|
* ]);
|
||||||
|
*
|
||||||
|
* class Foo {
|
||||||
|
* // Delend on `List<int>` normally.
|
||||||
|
* Foo(List<int> list) { ... }
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* This capability might be added to the language one day. See:
|
||||||
|
*
|
||||||
|
* https://code.google.com/p/dart/issues/detail?id=11923
|
||||||
|
*/
|
||||||
|
class TypeLiteral<T> {
|
||||||
|
const TypeLiteral();
|
||||||
|
Type get type => T;
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
/**
|
||||||
|
* Type literals is a Dart-only feature. This is here only so we can x-compile
|
||||||
|
* to multiple languages.
|
||||||
|
*/
|
||||||
|
export class TypeLiteral {
|
||||||
|
get type(): any { throw new Error("Type literals are only supported in Dart"); }
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
/// This file contains tests that make sense only in Dart
|
||||||
|
library angular2.test.di.integration_dart_spec;
|
||||||
|
|
||||||
|
import 'package:angular2/angular2.dart';
|
||||||
|
import 'package:angular2/di.dart';
|
||||||
|
import 'package:angular2/src/test_lib/test_bed.dart';
|
||||||
|
import 'package:angular2/test_lib.dart';
|
||||||
|
|
||||||
|
main() {
|
||||||
|
describe('TypeLiteral', () {
|
||||||
|
it('should publish via injectables',
|
||||||
|
inject([TestBed, AsyncTestCompleter], (tb, async) {
|
||||||
|
tb.overrideView(Dummy, new View(
|
||||||
|
template: '<type-literal-component></type-literal-component>',
|
||||||
|
directives: [TypeLiteralComponent]
|
||||||
|
));
|
||||||
|
|
||||||
|
tb.createView(Dummy).then((view) {
|
||||||
|
view.detectChanges();
|
||||||
|
expect(view.rootNodes).toHaveText('[Hello, World]');
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component(selector: 'dummy')
|
||||||
|
class Dummy {}
|
||||||
|
|
||||||
|
@Component(
|
||||||
|
selector: 'type-literal-component',
|
||||||
|
injectables: const [
|
||||||
|
const Binding(
|
||||||
|
const TypeLiteral<List<String>>(),
|
||||||
|
toValue: const <String>['Hello', 'World'])
|
||||||
|
]
|
||||||
|
)
|
||||||
|
@View(
|
||||||
|
template: '{{list}}'
|
||||||
|
)
|
||||||
|
class TypeLiteralComponent {
|
||||||
|
final List<String> list;
|
||||||
|
|
||||||
|
TypeLiteralComponent(this.list);
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
/// This file contains tests that make sense only in Dart
|
||||||
|
library angular2.test.di.injector_dart_spec;
|
||||||
|
|
||||||
|
import 'package:angular2/test_lib.dart';
|
||||||
|
import 'package:angular2/di.dart';
|
||||||
|
|
||||||
|
main() {
|
||||||
|
describe('Injector', () {
|
||||||
|
it('should support TypeLiteral', () {
|
||||||
|
var i = Injector.resolveAndCreate([
|
||||||
|
bind(new TypeLiteral<List<int>>()).toValue([1, 2, 3]),
|
||||||
|
Foo,
|
||||||
|
]);
|
||||||
|
expect(i.get(Foo).value).toEqual([1, 2, 3]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
final List<int> value;
|
||||||
|
Foo(this.value);
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
/// This file contains tests that make sense only in Dart
|
||||||
|
library angular2.test.di.key_dart_spec;
|
||||||
|
|
||||||
|
import 'package:angular2/test_lib.dart';
|
||||||
|
import 'package:angular2/di.dart';
|
||||||
|
|
||||||
|
main() {
|
||||||
|
describe('TypeLiteral', () {
|
||||||
|
it('contains type', () {
|
||||||
|
var t = new TypeLiteral<List<int>>();
|
||||||
|
expect('${t.type}').toEqual('List<int>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can be a constant', () {
|
||||||
|
var a = const TypeLiteral<List<int>>();
|
||||||
|
var b = const TypeLiteral<List<int>>();
|
||||||
|
expect(identical(a, b)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can be unique', () {
|
||||||
|
var a = const TypeLiteral<List<String>>();
|
||||||
|
var b = const TypeLiteral<List<int>>();
|
||||||
|
expect(identical(a, b)).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Key', () {
|
||||||
|
KeyRegistry registry;
|
||||||
|
|
||||||
|
beforeEach(() {
|
||||||
|
registry = new KeyRegistry();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('understands TypeLiteral', () {
|
||||||
|
var k = registry.get(const TypeLiteral<List<int>>());
|
||||||
|
expect('${k.token}').toEqual('List<int>');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
Loading…
Reference in New Issue