kiwi_generator 4.2.1 kiwi_generator: ^4.2.1 copied to clipboard
Generates dependency injection code using the kiwi package to reduce development time.
kiwi_generator #
Generates dependency injection code using the kiwi package to reduce development time.
Configuration #
dependencies:
kiwi: ^latest_version
- Add build_runner and
kiwi_generator
under thedev_dependencies:
section of thepubspec.yaml
file. The latest version is
dev_dependencies:
build_runner: ^2.3.3
kiwi_generator: ^latest_version
Usage #
In your library add the following import:
import 'package:kiwi/kiwi.dart';
Create an abstract class with an abstract method:
abstract class Injector {
void configure();
}
Annotate the abstract method with the kiwi Register
annotations.
abstract class Injector {
@Register.singleton(ServiceA)
@Register.factory(Service, from: ServiceB)
@Register.factory(ServiceB, name: 'factoryB')
@Register.factory(ServiceC, resolvers: {ServiceB: 'factoryB'})
void configure();
}
Include the part directive indicating the file that will be generated (typically the same file with a .g
extension before .dart
):
part 'test01.g.dart';
Run build_runner:
pub run build_runner build
For Flutter the command is different though:
flutter packages pub run build_runner build
Note: On first attempt to run this command you might encounter a conflict error. If so, please add the --delete-conflicting-outputs argument to your command:
flutter packages pub run build_runner build --delete-conflicting-outputs
(This additional argument allows the command to overwrite the .g.dart
file if necessary.)
You can also use the watch
command instead of build
. This will generate your file when it's saved.
pub run build_runner watch
A concrete class named _$TheNameOfYourAbstractClass
will be generated and you can call the method where you like.
For example you can create a function in your library which will call it:
void setup() {
var injector = _$Injector();
injector.configure();
}
Or you can create a function that will return the concrecte injector and use it elsewhere:
Injector getInjector() => _$Injector();
Annotations #
There is only one annotation, called Register
, with two constructors: factory
and singleton
. There are no constructor for registering instances because only const
instances are supported in metadata. And it would'nt be easier to create an annotation than registering directly with a container.
If you want to register a singleton (the factory will be called only one time, when accessing it for the first time):
@Register.singleton(ServiceA)
If you want to register a factory:
@Register.factory(ServiceA)
Both constructors have the same parameters:
Parameter | Type | Required | Description |
---|---|---|---|
type |
Type | Yes | This is the type to register |
name |
String | No | This is the name under which the factory will be registered |
from |
Type | No | The type to create when requesting type , if different of type . |
constructorName |
String | No | The name of the constructor to use inside the factory |
resolvers |
Map<String, String> | No | A map that give for a type, the name under which it should be resolved |
Short example #
This code:
import 'package:kiwi/kiwi.dart';
part 'test01.g.dart';
abstract class Injector {
@Register.singleton(ServiceA)
@Register.factory(Service, from: ServiceB)
@Register.factory(ServiceB, name: 'factoryB')
@Register.factory(ServiceC, resolvers: {ServiceB: 'factoryB'})
void common();
@Register.factory(ServiceC)
void development();
@Register.factory(ServiceC, constructorName: 'other')
void production();
}
class Service {}
class ServiceA extends Service {}
class ServiceB extends Service {
ServiceB(ServiceA serviceA);
}
class ServiceC extends Service {
ServiceC(ServiceA serviceA, ServiceB serviceB);
ServiceC.other(ServiceB serviceA);
}
void setup(bool isProduction) {
var injector = _$Injector();
injector.common();
if (isProduction) {
injector.production();
} else {
injector.development();
}
}
Will produce this:
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'test01.dart';
// **************************************************************************
// InjectorGenerator
// **************************************************************************
class _$Injector extends Injector {
void common() {
final KiwiContainer container = KiwiContainer();
container.registerSingleton((c) => ServiceA());
container
.registerFactory<Service>((c) => ServiceB(c<ServiceA>()));
container.registerFactory((c) => ServiceB(c<ServiceA>()), name: 'factoryB');
container.registerFactory(
(c) => ServiceC(c<ServiceA>(), c<ServiceB>('factoryB')));
}
void development() {
final KiwiContainer container = KiwiContainer();
container.registerFactory((c) => ServiceC(c<ServiceA>(), c<ServiceB>()));
}
void production() {
final KiwiContainer container = KiwiContainer();
container.registerFactory((c) => ServiceC.other(c<ServiceB>()));
}
}
Changelog #
Please see the Changelog page to know what's recently changed.