Build Status Coverage Status

Dice

Lightweight dependency injection framework for Dart.

Getting Started

Dice consists of two parts. * Modules containing your class registrations. * Injectors that uses the Module to inject instances into your code.

The following example should get you startd:

1. Add the Dice to your pubspec.yaml and run pub install

dependencies:
   dice: any

2. Create some classes and interfaces to inject

class BillingServiceImpl implements BillingService {
  @inject
  CreditProcessor _processor;
  
  Receipt chargeOrder(Order order, CreditCard creditCard) {
    if(!_processor.validate(creditCard)) {
      throw new ArgumentError("payment method not accepted");
    }
    // :
  }
}

3. Register types and classes in a module

class ExampleModule extends Module {
  configure() {
    // register [CreditProcessor] as a singleton
    register(CreditProcessor).toInstance(new CreditProcessorImpl());
    // register [BillingService] so a new version is created each time its requested
    register(BillingService).toType(BillingServiceImpl);
  }
}

4. Run it

import "package:dice/dice.dart";
main() {
	var injector = new Injector(new ExampleModule());
	var billingService = injector.getInstance(BillingService);
	var creditCard = new CreditCard("VISA");
	var order = new Order("Dart: Up and Running");
	billingService.chargeOrder(order, creditCard);
}

for more information see the full example here.

Dependency Injection with Dice

You can use the @inject annotation to mark objects and functions for injection the following ways:

  • Injection of public and private fields (object/instance variables)
class MyOtherClass {
  @inject
  SomeClass field;
  
  @inject
  SomeOtherClass _privateField;
}
  • Injection of constructor parameters
class MyClass {
  @inject
  MyClass(this.field);

  MyOtherClass field;
}
  • Injection of public and private setters
class SomeClass {
  @inject
  set value(SomeOtherClass val) => _privateValue = val;
  	
  @inject
  set _value(SomeOtherClass val) => _anotherPrivateValue = val;

  SomeOtherClass _privateValue, _anotherPrivateValue;
}

The injected objects are configured ether by extending the Module class and using one its register functions or directly on the Injector.

  • register type MyType to existing object (singleton injections)
register(MyType).toInstance(object)
  • register type MyType.
register(MyType)
  • register interface MyType to a class implementing it.
register(MyType).toType(MyTypeImpl)
  • register a typedef to a function matching it.
register(MyTypedef).toFunction(function)
  • register MyType to function that can build instances of it
register(MyType).toBuilder(() => new MyType())

Named Injections

Dice supports named injections by using the @Named annotation. Currently this annotation works everywhere the @inject annotation works, except for constructors.

class MyClass {
  @inject
  @Named('my-special-implementation')
  SomeClass _someClass;
}

The configuration is as before except you now provide an additional name paramater.

register(MyType, "my-name").toType(MyTypeImpl)

Advanced Features

  • Get instances directly Instead of using the @inject annotation to resolve injections you can use the injectors getInstance method.
MyClass instance = injector.getInstance(MyClass);
  • Get named instances directly Instead of using the @Named annotation to resolve named injections you can use the injectors getInstance method with its name parameter.
MyType instance = injector.getInstance(MyType, "my-name");
  • To register and resole configuration values You can use named registrations to inject configuration values into your application.
class TestModule extends Module {
  	configure() {
		register(String, "web-service-host").toInstace("http://test-service.name");
	}
}

// application code
String get webServiceHost => injector.getInstance(String, "web-service-host");
  • Registering dependencies at runtime You can register dependencies at runtime directly on the Injector.
 injector.register(User).toInstance(user);
 var user = injector.getInstance(User);
  • Unregistering dependencies at runtime You can unregister dependencies at runtime using the unregister method on the Injector.
injector.unregister(User);
  • Using multiple modules You can compose modules using the Injector.fromModules constructor.
class MyModule extends Module {
  	configure() {
		register(MyClass).toType(MyClass);
	}
}

class YourModule extends Module {
  	configure() {
		register(YourClass).toType(YourClass);
	}
}

var injector = new Injector.fromModules([new MyModule(), new YourModule()]);
var myClass = injector.getInstance(MyClass);
var yourClass = injector.getInstance(YourClass);
  • Joining injectors You can join multiple injector instances to one using the Injector.fromInjectors constructor.
var myInjector = new Injector();
myInjector.register(MyClass).toType(MyClass);

var yourInjector = new Injector();
yourInjector.register(YourClass).toType(YourClass);

var injector = new Injector.fromInjectors([myInjector, yourInjector]);
var myClass = injector.getInstance(MyClass);
var yourClass = injector.getInstance(YourClass);

Libraries

dice

Lightweight dependency injection framework for Dart.