fix(di): refactor bindings to support Dart annotations
This commit is contained in:
154
modules/angular2/src/di/binding.js
vendored
154
modules/angular2/src/di/binding.js
vendored
@ -1,9 +1,9 @@
|
||||
import {Type, isBlank, isPresent} from 'angular2/src/facade/lang';
|
||||
import {Type, isBlank, isPresent, CONST} from 'angular2/src/facade/lang';
|
||||
import {List, MapWrapper, ListWrapper} from 'angular2/src/facade/collection';
|
||||
import {reflector} from 'angular2/src/reflection/reflection';
|
||||
import {Key} from './key';
|
||||
import {Inject, InjectLazy, InjectPromise, Optional, DependencyAnnotation} from './annotations';
|
||||
import {NoAnnotationError} from './exceptions';
|
||||
import {NoAnnotationError, InvalidBindingError} from './exceptions';
|
||||
|
||||
export class Dependency {
|
||||
key:Key;
|
||||
@ -11,6 +11,7 @@ export class Dependency {
|
||||
lazy:boolean;
|
||||
optional:boolean;
|
||||
properties:List;
|
||||
|
||||
constructor(key:Key, asPromise:boolean, lazy:boolean, optional:boolean, properties:List) {
|
||||
this.key = key;
|
||||
this.asPromise = asPromise;
|
||||
@ -24,13 +25,100 @@ export class Dependency {
|
||||
}
|
||||
}
|
||||
|
||||
var _EMPTY_LIST = []; // TODO: make const when supported
|
||||
|
||||
/**
|
||||
* Declaration of a dependency binding.
|
||||
*/
|
||||
export class Binding {
|
||||
token;
|
||||
toClass:Type;
|
||||
toValue;
|
||||
toAlias;
|
||||
toFactory:Function;
|
||||
toAsyncFactory:Function;
|
||||
dependencies:List;
|
||||
|
||||
@CONST()
|
||||
constructor(
|
||||
token,
|
||||
{
|
||||
toClass,
|
||||
toValue,
|
||||
toAlias,
|
||||
toFactory,
|
||||
toAsyncFactory,
|
||||
deps
|
||||
}) {
|
||||
this.token = token;
|
||||
this.toClass = toClass;
|
||||
this.toValue = toValue;
|
||||
this.toAlias = toAlias;
|
||||
this.toFactory = toFactory;
|
||||
this.toAsyncFactory = toAsyncFactory;
|
||||
this.dependencies = deps;
|
||||
}
|
||||
|
||||
resolve(): ResolvedBinding {
|
||||
var factoryFn:Function;
|
||||
var resolvedDeps;
|
||||
var isAsync = false;
|
||||
if (isPresent(this.toClass)) {
|
||||
factoryFn = reflector.factory(this.toClass);
|
||||
resolvedDeps = _dependenciesFor(this.toClass);
|
||||
} else if (isPresent(this.toAlias)) {
|
||||
factoryFn = (aliasInstance) => aliasInstance;
|
||||
resolvedDeps = [Dependency.fromKey(Key.get(this.toAlias))];
|
||||
} else if (isPresent(this.toFactory)) {
|
||||
factoryFn = this.toFactory;
|
||||
resolvedDeps = _constructDependencies(this.toFactory, this.dependencies);
|
||||
} else if (isPresent(this.toAsyncFactory)) {
|
||||
factoryFn = this.toAsyncFactory;
|
||||
resolvedDeps = _constructDependencies(this.toAsyncFactory, this.dependencies);
|
||||
isAsync = true;
|
||||
} else {
|
||||
factoryFn = () => this.toValue;
|
||||
resolvedDeps = _EMPTY_LIST;
|
||||
}
|
||||
|
||||
return new ResolvedBinding(
|
||||
Key.get(this.token),
|
||||
factoryFn,
|
||||
resolvedDeps,
|
||||
isAsync
|
||||
);
|
||||
}
|
||||
|
||||
static resolveAll(bindings:List): List {
|
||||
var resolvedList = ListWrapper.createFixedSize(bindings.length);
|
||||
for (var i = 0; i < bindings.length; i++) {
|
||||
var unresolved = bindings[i];
|
||||
var resolved;
|
||||
if (unresolved instanceof Type) {
|
||||
resolved = bind(unresolved).toClass(unresolved).resolve();
|
||||
} else if (unresolved instanceof Binding) {
|
||||
resolved = unresolved.resolve();
|
||||
} else if (unresolved instanceof List) {
|
||||
resolved = Binding.resolveAll(unresolved);
|
||||
} else if (unresolved instanceof BindingBuilder) {
|
||||
throw new InvalidBindingError(unresolved.token);
|
||||
} else {
|
||||
throw new InvalidBindingError(unresolved);
|
||||
}
|
||||
resolvedList[i] = resolved;
|
||||
}
|
||||
return resolvedList;
|
||||
}
|
||||
}
|
||||
|
||||
/// Dependency binding with resolved keys and dependencies.
|
||||
export class ResolvedBinding {
|
||||
key:Key;
|
||||
factory:Function;
|
||||
dependencies:List;
|
||||
dependencies:List<Dependency>;
|
||||
providedAsPromise:boolean;
|
||||
|
||||
constructor(key:Key, factory:Function, dependencies:List, providedAsPromise:boolean) {
|
||||
constructor(key:Key, factory:Function, dependencies:List<Dependency>, providedAsPromise:boolean) {
|
||||
this.key = key;
|
||||
this.factory = factory;
|
||||
this.dependencies = dependencies;
|
||||
@ -38,66 +126,54 @@ export class Binding {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides fluent API for imperative construction of [Binding] objects.
|
||||
*/
|
||||
export function bind(token):BindingBuilder {
|
||||
return new BindingBuilder(token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper class for [bind] function.
|
||||
*/
|
||||
export class BindingBuilder {
|
||||
token;
|
||||
|
||||
constructor(token) {
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
toClass(type:Type):Binding {
|
||||
return new Binding(
|
||||
Key.get(this.token),
|
||||
reflector.factory(type),
|
||||
_dependenciesFor(type),
|
||||
false
|
||||
);
|
||||
return new Binding(this.token, {toClass: type});
|
||||
}
|
||||
|
||||
toValue(value):Binding {
|
||||
return new Binding(
|
||||
Key.get(this.token),
|
||||
() => value,
|
||||
[],
|
||||
false
|
||||
);
|
||||
return new Binding(this.token, {toValue: value});
|
||||
}
|
||||
|
||||
toAlias(aliasToken):Binding {
|
||||
return new Binding(
|
||||
Key.get(this.token),
|
||||
(aliasInstance) => aliasInstance,
|
||||
[Dependency.fromKey(Key.get(aliasToken))],
|
||||
false
|
||||
);
|
||||
return new Binding(this.token, {toAlias: aliasToken});
|
||||
}
|
||||
|
||||
toFactory(factoryFunction:Function, dependencies:List = null):Binding {
|
||||
return new Binding(
|
||||
Key.get(this.token),
|
||||
factoryFunction,
|
||||
this._constructDependencies(factoryFunction, dependencies),
|
||||
false
|
||||
);
|
||||
return new Binding(this.token, {
|
||||
toFactory: factoryFunction,
|
||||
deps: dependencies
|
||||
});
|
||||
}
|
||||
|
||||
toAsyncFactory(factoryFunction:Function, dependencies:List = null):Binding {
|
||||
return new Binding(
|
||||
Key.get(this.token),
|
||||
factoryFunction,
|
||||
this._constructDependencies(factoryFunction, dependencies),
|
||||
true
|
||||
);
|
||||
return new Binding(this.token, {
|
||||
toAsyncFactory: factoryFunction,
|
||||
deps: dependencies
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
_constructDependencies(factoryFunction:Function, dependencies:List) {
|
||||
return isBlank(dependencies) ?
|
||||
_dependenciesFor(factoryFunction) :
|
||||
ListWrapper.map(dependencies, (t) => Dependency.fromKey(Key.get(t)));
|
||||
}
|
||||
function _constructDependencies(factoryFunction:Function, dependencies:List) {
|
||||
return isBlank(dependencies) ?
|
||||
_dependenciesFor(factoryFunction) :
|
||||
ListWrapper.map(dependencies, (t) => Dependency.fromKey(Key.get(t)));
|
||||
}
|
||||
|
||||
function _dependenciesFor(typeOrFunc):List {
|
||||
|
Reference in New Issue
Block a user