refactor(injector): use @CONST to create the Inject annotation

This commit is contained in:
vsavkin
2014-10-03 20:34:37 -04:00
parent f63a5dd158
commit a814d48bbc
5 changed files with 12 additions and 21 deletions

View File

@ -1,7 +1,8 @@
//TODO: vsavkin: uncomment once const constructor are supported
//export class Inject {
// @CONST
// constructor(token){
// this.token = token;
// }
//}
import {CONST} from "facade/lang";
export class Inject {
@CONST()
constructor(token){
this.token = token;
}
}

View File

@ -1,6 +1,6 @@
import {Type} from 'facade/lang';
import {List, MapWrapper, ListWrapper} from 'facade/collection';
import {Reflector} from 'facade/di/reflector';
import {Reflector} from './reflector';
import {Key} from './key';
export class Binding {

View File

@ -1,5 +1,5 @@
export * from './annotations';
export * from './injector';
export * from './binding';
export * from './key';
export * from './module';
export {Inject} from 'facade/di/reflector';

View File

@ -0,0 +1,53 @@
library facade.di.reflector;
import 'dart:mirrors';
import 'annotations.dart' show Inject;
class Reflector {
factoryFor(Type type) {
return _generateFactory(type);
}
convertToFactory(Function factory) {
return (args) => Function.apply(factory, args);
}
Function _generateFactory(Type type) {
ClassMirror classMirror = reflectType(type);
MethodMirror ctor = classMirror.declarations[classMirror.simpleName];
Function create = classMirror.newInstance;
Symbol name = ctor.constructorName;
return (args) => create(name, args).reflectee;
}
dependencies(Type type) {
ClassMirror classMirror = reflectType(type);
MethodMirror ctor = classMirror.declarations[classMirror.simpleName];
return new List.generate(ctor.parameters.length, (int pos) {
ParameterMirror p = ctor.parameters[pos];
if (p.type.qualifiedName == #dynamic) {
var name = MirrorSystem.getName(p.simpleName);
throw "Error getting params for '$type': "
"The '$name' parameter must be typed";
}
if (p.type is TypedefMirror) {
throw "Typedef '${p.type}' in constructor "
"'${classMirror.simpleName}' is not supported.";
}
ClassMirror pTypeMirror = (p.type as ClassMirror);
var pType = pTypeMirror.reflectedType;
final inject = p.metadata.map((m) => m.reflectee).where((m) => m is Inject);
if (inject.isNotEmpty) {
return inject.first.token;
} else {
return pType;
}
}, growable:false);
}
}

View File

@ -0,0 +1,35 @@
import {Type} from 'facade/lang';
import {Inject} from './annotations';
export class Reflector {
factoryFor(type:Type) {
return (args) => new type(...args);
}
convertToFactory(factoryFunction:Function) {
return (args) => factoryFunction(...args);
}
dependencies(type:Type) {
var p = type.parameters;
if (p == undefined) return [];
return type.parameters.map((p) => this._extractToken(p));
}
_extractToken(annotations) {
var type, inject;
for (var paramAnnotation of annotations) {
if (isFunction(paramAnnotation)) {
type = paramAnnotation;
} else if (paramAnnotation instanceof Inject) {
inject = paramAnnotation.token;
}
}
return inject != undefined ? inject : type;
}
}
function isFunction(value) {
return typeof value === 'function';
}