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

DI 2.0.0 #135

Merged
merged 5 commits into from
Jul 23, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ test/main.dart.js.deps
test/main.dart.js.map
test/main.dart.precompiled.js
test/transformer/build
benchmark/generated_files/
examples/build
out
build
benchmark/generated_files/*
58 changes: 57 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,60 @@
# 2.0.0

## Breaking Changes

### Calls to `StaticInjector` and `DynamicInjector` should be replaced with `ModuleInjector`
- There are no longer `StaticInjectors` and `DynamicInjectors`. They have been replaced
by a new `ModuleInjector` class that acts as both types of injectors.

### ModuleInjectors have no visibility
- All bindings and instances of parent injectors are now visible in child injectors.
- The optional argument `forceNewInstances` of `Injector.createChild` has been removed
Instead, create a new module with bindings of the types that require new instances
and pass that to the child injector, and the child injector will create new
instances instead of returning the instance of the parent injector.

### Use `new ModuleInjector(modules, parent)` instead of `Injector.createChild(modules)`
- The latter is still available but deprecated.
- Injectors with no parent now have a dummy RootInjector instance as the parent
Instead of checking “parent == null”, check for “parent == rootInjector”.

### Injectors no longer have a name field
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ModuleInjector still has a name field - one of the two places needs to be fixed


### typeFactories have changed
- Old type factories had the form `(injector) => new Instance(injector.get(dep1), … )`
- New factories have the form:
- `toFactory(a0, a1, …) => new Instance(a0, a1, …)`
- When calling `Module.bind(toFactory: factory)`, there is an additional argument `inject`
of a list of types or keys (preferred for performance) whose instances should be
passed to the factory. The arguments passed to the factory function will be instances
of the types in `inject`.

Example:
- Old code `module.bind(Car, toFactory: (i) => new Car(i.get(Engine)));`
- New code
- `module.bind(Car, toFactory: (engine) => new Car(engine), inject: [Engine]);`

There is also some syntactic sugar for this special case.
- Old code `module.bind(V8Engine, toFactory: (i) => i.get(Engine));`
- New code `module.bind(V8Engine, toFactory: (e) => e, inject: [Engine]);`
- With sugar `module.bind(V8Engine, toInstanceOf: Engine);`

### Modules have a `TypeReflector` instance attached
- The `TypeReflector` is how the module will find the `toFactory` and `inject`
arguments when not explicitly specified. This is either done with mirroring or code
generation via transformers. Transformers will set the default to use code gen.
For testing and other special purposes where a specific reflector is needed, use
`new Module.withReflector(reflector)`.

### The transformer has been updated
- Running the transformer will do the necessary code generation and edits to switch the
default `TypeReflector` from mirroring to static factories. Enable transformer to use
static factories, disable to use mirrors. More docs on the transformer can be found in
`transformer.dart`

### Deprecated module methods removed
- `.value`, `.type`, `.factory`, `.factoryByKey` are gone. Use `..bind`.

# 1.2.3

## Features
Expand Down Expand Up @@ -35,7 +92,6 @@ Added missing library declaration to injector.
- **injector:** optimized module to injector instantiation
([62f22f15](https://github.com/angular/di.dart/commit/62f22f1566642cecc1b9f980475c94a7a88e9362))


# 1.0.0

Starting with this release DI is following [semver](http://semver.org).
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License

Copyright (c) 2013 Google, Inc.
Copyright (c) 2014 Google, Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
20 changes: 13 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,29 @@
Add dependency to your pubspec.yaml.

dependencies:
di: ">=0.0.39 <0.1.0"
di: ">=2.0.0 <3.0.0"

Then, run `pub install`.

Import di.

import 'package:di/di.dart';
import 'package:di/auto_injector.dart';

## Example

```dart
import 'package:di/di.dart';
import 'package:di/auto_injector.dart';

abstract class Engine {
go();
}

class Fuel {}

class V8Engine implements Engine {
Fuel fuel;
V8Engine(this.fuel);

go() {
print('Vroom...');
}
Expand Down Expand Up @@ -64,14 +67,17 @@ class ElectricCar {
}

void main() {
var injector = defaultInjector(modules: [new Module()
var injector = new ModuleInjector(modules: [new Module()
..bind(GenericCar)
..bind(ElectricCar)
..bind(Engine, toFactory: (i) => new V8Engine())
..bind(Engine, toFactory: (fuel) => new V8Engine(fuel), inject: [Fuel])
..bind(Engine, toImplementation: ElectricEngine, withAnnotation: Electric)
]);
injector.get(GenericCar).drive();
injector.get(ElectricCar).drive();
injector.get(GenericCar).drive(); // Vroom...
injector.get(ElectricCar).drive(); // Hum...
}
```

## Contributing

Refer to the guidelines for [contributing to AngularDart](http://goo.gl/nrXVgm).
7 changes: 3 additions & 4 deletions benchmark/dynamic_injector_benchmark.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import 'package:benchmark_harness/benchmark_harness.dart';
import 'package:di/dynamic_injector.dart';
import 'package:di/src/reflector_dynamic.dart';

import 'injector_benchmark_common.dart';


main() {
new InjectorBenchmark('DynamicInjectorBenchmark',
(m) => new DynamicInjector(modules: m)).report();
}
new DynamicTypeFactories()).report();
}
73 changes: 54 additions & 19 deletions benchmark/injector_benchmark_common.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,43 @@ import 'package:di/di.dart';
int count = 0;

class InjectorBenchmark extends BenchmarkBase {
var injectorFactory;
var module;
var typeReflector;
Key KEY_A;
Key KEY_B;
Key KEY_C;
Key KEY_D;
Key KEY_E;

InjectorBenchmark(name, this.injectorFactory) : super(name);
InjectorBenchmark(name, this.typeReflector) : super(name);

void run() {
Injector injector = injectorFactory([module]);
injector.get(A);
injector.get(B);
Injector injector = new ModuleInjector([module]);
injector.getByKey(KEY_A);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move these benchmark changes to a PR on top of DI 1

injector.getByKey(KEY_B);

var childInjector = injector.createChild([module]);
childInjector.get(A);
childInjector.get(B);
var childInjector = new ModuleInjector([module], injector);
childInjector.getByKey(KEY_A);
childInjector.getByKey(KEY_B);
}

setup() {
module = new Module()
..type(A)
..type(B)
..type(C)
..type(C, withAnnotation: AnnOne, implementedBy: COne )
..type(D)
..type(E)
..type(E, withAnnotation: AnnTwo, implementedBy: ETwo )
..type(F)
..type(G);
module = new Module.withReflector(typeReflector)
..bind(A)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move these benchmark changes to a PR on top of DI 1

..bind(B)
..bind(C)
..bind(C, withAnnotation: AnnOne, toImplementation: COne )
..bind(D)
..bind(E)
..bind(E, withAnnotation: AnnTwo, toImplementation: ETwo )
..bind(F)
..bind(G);

KEY_A = new Key(A);
KEY_B = new Key(B);
KEY_C = new Key(C);
KEY_D = new Key(D);
KEY_E = new Key(E);
}

teardown() {
Expand Down Expand Up @@ -96,7 +107,31 @@ class F {
}

class G {
G(@AnnTwo() E) {
G(@AnnTwo() E e) {
count++;
}
}

var typeFactories = {
A: (a1, a2) => new A(a1, a2),
B: (a1, a2) => new B(a1, a2),
C: () => new C(),
D: () => new D(),
E: () => new E(),
COne: () => new COne(),
ETwo: () => new ETwo(),
F: (a1, a2) => new F(a1, a2),
G: (a1) => new G(a1),
};

var paramKeys = {
A: [new Key(B), new Key(C)],
B: [new Key(D), new Key(E)],
C: const [],
D: const [],
E: const [],
COne: const [],
ETwo: const [],
F: [new Key(C, AnnOne), new Key(D)],
G: [new Key(G, AnnTwo)],
};
17 changes: 5 additions & 12 deletions benchmark/instance_benchmark.dart
Original file line number Diff line number Diff line change
@@ -1,29 +1,22 @@
import 'package:di/static_injector.dart';
import 'package:di/di.dart';
import 'package:di/src/reflector_static.dart';

import 'injector_benchmark_common.dart';

// tests the speed of cached getInstanceByKey requests
class InstanceBenchmark extends InjectorBenchmark{
InstanceBenchmark(name, injectorFactory) : super(name, injectorFactory);
InstanceBenchmark(name, typeReflector) : super(name, typeReflector);

void run(){
Injector injector = injectorFactory([module]);
Injector injector = new ModuleInjector([module]);
for (var i = 0; i < 30; i++) {
injector.get(A);
}
}
}

main() {
var typeFactories = {
A: (f) => new A(f(B), f(C)),
B: (f) => new B(f(D), f(E)),
C: (f) => new C(),
D: (f) => new D(),
E: (f) => new E(),
};

new InstanceBenchmark('InstanceBenchmark',
(m) => new StaticInjector(modules: m, typeFactories: typeFactories)
new GeneratedTypeFactories(typeFactories, paramKeys)
).report();
}
70 changes: 70 additions & 0 deletions benchmark/large_benchmark.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import 'package:benchmark_harness/benchmark_harness.dart';
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Create a PR to add this benchmark to DI 1

(this PR will still need changes to upgrade it to DI 2)

import 'package:di/di.dart';
import 'package:di/src/reflector_static.dart';
import 'generated_files/factories.dart';

import 'dart:math';

class LargeBenchmark extends BenchmarkBase {
var injectorFactory;
Injector rootInjector;
Injector leafInjector;
var leafKey;
var rng = new Random();
var numInjectors = 1;
var allLeaves = [];

LargeBenchmark(name, this.injectorFactory) : super("Large" + name);

setup() {
var rootModule = new Module()
..bindByKey(key999)
..bindByKey(key998)
..bindByKey(key997)
..bindByKey(key996)
..bindByKey(key995);
rootInjector = injectorFactory([rootModule]);

createChildren (injector, depth, width) {
if (depth <= 0){
allLeaves.add(injector);
return;
}
for (var i=0; i<width; i++){
var module = new Module();
for (var j=0; j<5; j++){
leafKey = allKeys[rng.nextInt(995)];
module.bindByKey(leafKey);
}
leafInjector = injector.createChild([module]);
numInjectors++;
createChildren(leafInjector, depth-1, width);
}
}

createChildren(rootInjector, 5, 5);
print("$numInjectors injectors created.");
}
}

class GetFromRoot extends LargeBenchmark {
GetFromRoot() : super('FromRoot', (m) => new ModuleInjector(m));

run() {
leafInjector.getByKey(key999);
}
}

class GetFromLeaf extends LargeBenchmark {
GetFromLeaf() : super('FromLeaf', (m) => new ModuleInjector(m));

run() {
leafInjector.getByKey(leafKey);
}
}

main() {
Module.DEFAULT_REFLECTOR = new GeneratedTypeFactories(typeFactories, parameterKeys);
new GetFromRoot().report();
new GetFromLeaf().report();
}
17 changes: 11 additions & 6 deletions benchmark/module_benchmark.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,26 @@ import 'package:di/di.dart';

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move the changes in this file to a DI 1 PR

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

import 'injector_benchmark_common.dart';

/**
* tests the speed of looking up typeFactories and binding them to
* a module. Mirroring time is not counted because DynamicTypeFactories
* caches the results.
*/
class ModuleBenchmark extends BenchmarkBase {
var injectorFactory;

ModuleBenchmark() : super('ModuleBenchmark');

void run() {
var m = new Module()
..type(A)
..type(B)
..type(C)
..type(D)
..type(E);
..bind(A)
..bind(B)
..bind(C)
..bind(D)
..bind(E);
}
}

main() {
new ModuleBenchmark().report();
}
}
Loading