velix_di 0.9.0+3
velix_di: ^0.9.0+3 copied to clipboard
a flutter dependency injection framework.
Introduction #
Velix is Dart/Flutter library implementing some of the core parts required in every Flutter application:
- type meta data
- specification and validation of type constraints
- general purpose mapping framework
- json mapper
- model-based two-way form data-binding
- i18n
- dependency injection container
- command pattern for ui actions
Check out some articles on Medium:
Detailed information can be found in the corresponding Wiki.
Lets get a quick overview on the topics
Validation #
As in some popular Typescript libraries like yup, it is possible to declare type constraints with a simple fluent language
var type = IntType().greaterThan(0).lessThan(100);
type.validate(-1); // meeeh....will throw
Type Meta-Data #
In combination with a custom code generator, classes decorated with specific annotations - here @Dataclass- emit the meta data:
@Dataclass()
class Money {
// instance data
@Attribute(type: "length 7")
final String currency;
@Attribute(type: ">= 0")
final int value;
const Money({required this.currency, required this.value});
}
The information will be used by a number of mechanisms, such as
- dependency injection container
- the mapping framework
- form data-binding.
Dependency Injection #
A DI solution similar based on the existing meta-data has been created, that let's a container handle the lifecycle of objects.
Example:
// a module defines the set of managed objects according to their library location
// it can import other modules!
@Module(imports: [])
class TestModule {
@Create()
ConfigurationManager createConfigurationManager() {
return ConfigurationManager();
}
// factory method
@Create()
ConfigurationValues createConfigurationValues() {
// will register with the configuration manager via a lifecycle method!
return ConfigurationValues({
"foo": 4711
});
}
}
// singleton is the default, btw.
@Injectable(scope: "singleton", eager: false)
class Bar {
const Bar();
}
// environment means that it is a singleton per environment
@Injectable(scope: "environment")
class Foo {
// instance data
final Bar bar;
// constructor injection
const Foo({required this.bar});
}
@Injectable()
class Factory {
const Factory();
// some lifecycle callbacks
// injection of the surrounding environment
@OnInit()
void onInit(Environment environment) {
...
}
@OnDestroy()
void onDestroy() {
...
}
// config value injection!
@Inject()
void setFoo(Foo foo, @Value("foo", defaultValue: 1) int value) {
...
}
// another method based factory
@Create()
Baz createBaz(Bar bar) {
return Baz();
}
}
var environment = Environment(forModule: TestModule);
var foo = environment.get<Foo>();
var inherited = Environment(parent: environment);
var inheritedFoo = environment.get<Foo>(); // will be another instance, since it has the scope "environment"
Features are:
- constructor and setter injection
- injection of configuration variables
- possibility to define custom injections
- post processors
- support for factory methods
- support for eager and lazy construction
- support for scopes "singleton", "request" and "environment"
- possibility to add custom scopes
- conditional registration of classes and factories ( aka profiles in spring )
- lifecycle events methods
@OnInit,@OnDestroy,@OnRunning - Automatic discovery and bundling of injectable objects based on their module location, including support for recursive imports
- Instantiation of one or possible more isolated container instances — called environments — each managing the lifecycle of a related set of objects,
- Support for hierarchical environments, enabling structured scoping and layered object management.
Installation #
The library is published on pub.dev