2015-03-26 10:51:44 +01:00

154 lines
4.0 KiB
JavaScript

import {Type, isBlank, isPresent} 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';
export class Dependency {
key:Key;
asPromise:boolean;
lazy:boolean;
optional:boolean;
properties:List;
constructor(key:Key, asPromise:boolean, lazy:boolean, optional:boolean, properties:List) {
this.key = key;
this.asPromise = asPromise;
this.lazy = lazy;
this.optional = optional;
this.properties = properties;
}
static fromKey(key:Key) {
return new Dependency(key, false, false, false, []);
}
}
export class Binding {
key:Key;
factory:Function;
dependencies:List;
providedAsPromise:boolean;
constructor(key:Key, factory:Function, dependencies:List, providedAsPromise:boolean) {
this.key = key;
this.factory = factory;
this.dependencies = dependencies;
this.providedAsPromise = providedAsPromise;
}
}
export function bind(token):BindingBuilder {
return new BindingBuilder(token);
}
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
);
}
toValue(value):Binding {
return new Binding(
Key.get(this.token),
() => value,
[],
false
);
}
toAlias(aliasToken):Binding {
return new Binding(
Key.get(this.token),
(aliasInstance) => aliasInstance,
[Dependency.fromKey(Key.get(aliasToken))],
false
);
}
toFactory(factoryFunction:Function, dependencies:List = null):Binding {
return new Binding(
Key.get(this.token),
factoryFunction,
this._constructDependencies(factoryFunction, dependencies),
false
);
}
toAsyncFactory(factoryFunction:Function, dependencies:List = null):Binding {
return new Binding(
Key.get(this.token),
factoryFunction,
this._constructDependencies(factoryFunction, dependencies),
true
);
}
_constructDependencies(factoryFunction:Function, dependencies:List) {
return isBlank(dependencies) ?
_dependenciesFor(factoryFunction) :
ListWrapper.map(dependencies, (t) => Dependency.fromKey(Key.get(t)));
}
}
function _dependenciesFor(typeOrFunc):List {
var params = reflector.parameters(typeOrFunc);
if (isBlank(params)) return [];
if (ListWrapper.any(params, (p) => isBlank(p))) throw new NoAnnotationError(typeOrFunc);
return ListWrapper.map(params, (p) => _extractToken(typeOrFunc, p));
}
function _extractToken(typeOrFunc, annotations) {
var depProps = [];
var token = null;
var optional = false;
var lazy = false;
var asPromise = false;
for (var i = 0; i < annotations.length; ++i) {
var paramAnnotation = annotations[i];
if (paramAnnotation instanceof Type) {
token = paramAnnotation;
} else if (paramAnnotation instanceof Inject) {
token = paramAnnotation.token;
} else if (paramAnnotation instanceof InjectPromise) {
token = paramAnnotation.token;
asPromise = true;
} else if (paramAnnotation instanceof InjectLazy) {
token = paramAnnotation.token;
lazy = true;
} else if (paramAnnotation instanceof Optional) {
optional = true;
} else if (paramAnnotation instanceof DependencyAnnotation) {
ListWrapper.push(depProps, paramAnnotation);
} else if (paramAnnotation.name === "string") {
token = paramAnnotation;
}
}
if (isPresent(token)) {
return _createDependency(token, asPromise, lazy, optional, depProps);
} else {
throw new NoAnnotationError(typeOrFunc);
}
}
function _createDependency(token, asPromise, lazy, optional, depProps):Dependency {
return new Dependency(Key.get(token), asPromise, lazy, optional, depProps);
}