Skip to content
This repository was archived by the owner on Dec 6, 2017. It is now read-only.

Commit

Permalink
Initial super lame version
Browse files Browse the repository at this point in the history
  • Loading branch information
vojtajina committed Apr 9, 2013
0 parents commit fc062a7
Show file tree
Hide file tree
Showing 8 changed files with 227 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
packages
pubspec.lock
18 changes: 18 additions & 0 deletions Gruntfile.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
spawn = require('child_process').spawn

DART_VM = process.env.DART_VM or '../dart-sdk/bin/dart'

module.exports = (grunt) ->
grunt.initConfig
watch:
tests:
files: ['test/**/*.dart', 'lib/**/*.dart']
tasks: ['dart']
dart:
tests:
entry: 'test/main.dart'

grunt.registerMultiTask 'dart', 'run dart program', ->
spawn(DART_VM, [@data.entry], {stdio: 'inherit'}).on 'close', @async()

grunt.loadNpmTasks 'grunt-contrib-watch'
66 changes: 66 additions & 0 deletions lib/di.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import 'mirrors.dart';
import 'dart:async';

class Injector {
// should be <Type,Type>
Map<String, String> providers = new Map<String, String>();
// should be <Type, dynamic>
Map<String, dynamic> instances = new Map<String, dynamic>();

Injector([Map types]) {
if (types != null) {
// create <String,String> map, because Dart is stupid and makes us deal with strings rather than types
types.forEach((key, value) {
providers[key.toString()] = value.toString();
});
}
}

ClassMirror _getClassMirrorByTypeName (String typeName) {
// overriden provider
if (providers.containsKey(typeName)) {
typeName = providers[typeName];
}

for (var lib in currentMirrorSystem().libraries.values) {
if (lib.classes.containsKey(typeName)) {
return lib.classes[typeName];
}
}
}

ClassMirror _getClassMirrorFromType(Type type) {
// terrible hack because we can't get a qualified name from a Type
// dartbug.com/8041
// dartbug.com/9395
return _getClassMirrorByTypeName(type.toString());
}


dynamic _getInstanceByTypeName(String typeName) {
if (instances.containsKey(typeName)) {
return instances[typeName];
}

ClassMirror cm = _getClassMirrorByTypeName(typeName);
MethodMirror ctor = cm.constructors.values.first;

resolveArgument(p) {
return _getInstanceByTypeName(p.type.simpleName);
}

var positionalArgs = ctor.parameters.map(resolveArgument).toList();
var namedArgs = null;
var instance = deprecatedFutureValue(cm.newInstance(ctor.constructorName, positionalArgs, namedArgs));

instances[typeName] = instance;

return instance;
}


// PUBLIC API
dynamic get(Type type) {
return _getInstanceByTypeName(type.toString()).reflectee;
}
}
4 changes: 4 additions & 0 deletions lib/mirrors.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// just to get rid of the warning
library mirrors;

export 'dart:mirrors';
17 changes: 17 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "dart-di",
"version": "0.0.0",
"description": "ERROR: No README.md file found!",
"main": "index.js",
"dependencies": {},
"devDependencies": {
"grunt": "~0.4",
"grunt-contrib-watch": "~0.3"
},
"scripts": {
"test": "grunt dart:test"
},
"repository": "",
"author": "Vojta Jina <[email protected]>",
"license": "MIT"
}
8 changes: 8 additions & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
name: di
description: A prototype of Dependency Injection framework.
version: 0.0.1
author: "Vojta Jina <[email protected]>"
homepage: https://github.com/dart-lang/dado

dev_dependencies:
unittest: any
33 changes: 33 additions & 0 deletions test/fixed-unittest.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
library unittest;

import 'package:unittest/unittest.dart';
import '../lib/mirrors.dart';

export 'package:unittest/unittest.dart';

// fix the testing framework ;-)
void it(String spec, TestFunction body) => test(spec, body);
void xit(String spec, TestFunction body) {}
void iit(String spec, TestFunction body) => solo_test(spec, body);

Matcher toEqual(expected) => equals(expected);
Matcher toBe(expected) => same(expected);
Matcher instanceOf(Type t) => new IsInstanceOfTypeMatcher(t);


// Welcome to Dart ;-)
class IsInstanceOfTypeMatcher extends BaseMatcher {
Type t;

IsInstanceOfTypeMatcher(Type t) {
this.t = t;
}

bool matches(obj, MatchState matchState) {
// we should at least compare qualifiedName, but there's no way to get it from Type
return reflect(obj).type.simpleName == t.toString();
}

Description describe(Description description) =>
description.add('an instance of ${t.toString()}');
}
78 changes: 78 additions & 0 deletions test/main.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import 'fixed-unittest.dart';
import 'package:di/di.dart';

// just some classes for testing
class Abc {
String id = 'abc-id';

void greet() {
print('HELLO');
}
}

class MockAbc implements Abc {
String id = 'mock-id';

void greet() {
print('MOCK HELLO');
}
}

class Complex {
Abc value;

Complex(Abc val) {
value = val;
}

dynamic getValue() {
return value;
}
}


// pretend, you don't see this main method
void main() {

it('should instantiate a type', () {
var injector = new Injector();
var instance = injector.get(Abc);

expect(instance, instanceOf(Abc));
expect(instance.id, toEqual('abc-id'));
});


it('should resolve basic dependencies', () {
var injector = new Injector();
var instance = injector.get(Complex);

expect(instance, instanceOf(Complex));
expect(instance.getValue().id, toEqual('abc-id'));
});


it('should allow modules and overriding providers', () {
// module is just a Map<Type, Type>
var module = new Map<Type, Type>();
module[Abc] = MockAbc;

// injector is immutable
// you can't load more modules once it's instantiated
// (you can create a child injector)
var injector = new Injector(module);
var instance = injector.get(Abc);

expect(instance.id, toEqual('mock-id'));
});


it('should only create a single instance', () {
var injector = new Injector();
var first = injector.get(Abc);
var second = injector.get(Abc);

expect(first, toBe(second));
});

}

0 comments on commit fc062a7

Please sign in to comment.