feat(injector): initial implementaion of dynamic injector

This commit is contained in:
vsavkin
2014-09-30 14:56:33 -04:00
parent 6c8da62c1b
commit b2199632c7
24 changed files with 792 additions and 44 deletions

View File

@ -0,0 +1,14 @@
library angular.core.facade.async;
import 'dart:async';
export 'dart:async' show Future;
class FutureWrapper {
static Future value(obj) {
return new Future.value(obj);
}
static Future wait(List<Future> futures){
return Future.wait(futures);
}
}

View File

@ -0,0 +1,12 @@
export var Future = Promise;
export class FutureWrapper {
static value(obj):Future {
return Future.resolve(obj);
}
static wait(futures):Future {
if (futures.length == 0) return Future.resolve([]);
return Future.all(futures);
}
}

View File

@ -8,14 +8,25 @@ class MapWrapper {
static get(m, k) => m[k];
static void set(m, k, v){ m[k] = v; }
static contains(m, k) => m.containsKey(k);
static forEach(m, fn) {
m.forEach(fn);
}
}
class ListWrapper {
static List clone(List l) => new List.from(l);
static List create() => new List();
static List createFixedSize(int size) => new List(size);
static get(m, k) => m[k];
static void set(m, k, v) { m[k] = v; }
static contains(m, k) => m.containsKey(k);
static map(list, fn) => list.map(fn).toList();
static forEach(list, fn) {
list.forEach(fn);
}
static last(list) {
return list.last;
}
static void push(List l, e) { l.add(e); }
}

View File

@ -6,21 +6,41 @@ export class MapWrapper {
static create():HashMap { return new HashMap(); }
static get(m, k) { return m[k]; }
static set(m, k, v) { m[k] = v; }
static contains(m, k) { return m.containsKey(k); }
static contains(m, k) { return m[k] != undefined; }
static forEach(m, fn) {
for(var k in m) {
fn(k, m[k]);
}
}
}
export class ListWrapper {
static create():List { return new List(); }
static createFixedSize(size):List { return new List(); }
static get(m, k) { return m[k]; }
static set(m, k, v) { m[k] = v; }
static clone(array) {
return Array.prototype.slice.call(array, 0);
}
static push(l, e) { l.push(e); }
static map(array, fn) {
return array.map(fn);
}
static forEach(array, fn) {
for(var p of array) {
fn(p);
}
}
static push(array, el) {
array.push(el);
}
static last(array) {
if (!array || array.length == 0) return null;
return array[array.length - 1];
}
}
export class SetWrapper {
static createFromList(lst:List) { return new Set(lst); }
static has(s:Set, key):boolean { return s.has(key); }
}
}

View File

@ -0,0 +1,57 @@
library facade.di.reflector;
import 'dart:mirrors';
class Inject {
final Object token;
const Inject(this.token);
}
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,41 @@
import {Type} from 'facade/lang';
//TODO: vsvakin: remove when const constructors are implemented
export class Inject {
constructor(token){
this.token = token;
}
}
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';
}

View File

@ -1,7 +1,6 @@
library angular.core.facade.async;
library angular.core.facade.lang;
export 'dart:async' show Future;
export 'dart:core' show Type, int;
export 'dart:core' show Type;
class FIELD {
final String definition;
@ -19,6 +18,10 @@ class IMPLEMENTS {
const IMPLEMENTS(this.interfaceClass);
}
bool isPresent(obj) => obj != null;
bool isBlank(obj) => obj == null;
String humanize(obj) => obj.toString();
class StringWrapper {
static String fromCharCode(int code) {

View File

@ -1,4 +1,3 @@
export var Future = Promise;
export var Type = Function;
export class FIELD {
@ -12,6 +11,30 @@ export class ABSTRACT {}
export class IMPLEMENTS {}
export function isPresent(obj){
return obj != undefined && obj != null;
}
export function isBlank(obj){
return obj == undefined || obj == null;
}
export function humanize(token) {
if (typeof token === 'string') {
return token;
}
if (token === undefined || token === null) {
return '' + token;
}
if (token.name) {
return token.name;
}
return token.toString();
}
export class StringWrapper {
static fromCharCode(code:int) {
return String.fromCharCode(code);