Build 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.