Last updated:
0 purchases
managed
Small dependency injection library.
Pure, dependency free library for dependency injection without code generation and with small as possible boilerplate.
Features #
Multitype dependency registration.
Scope based dependency registration.
Simple injection API
Dependency registration #
This library uses Module primitive for dependency registration code. When
you want to register dependency for injection you should do next things.
Define module where dependency registration code will be declared.
class AppModule extends Module {
AppModule() : super({});
}
copied to clipboard
You can define more than one module. The amount of modules depends on your app
architecture.
Declare one or more dependency registration instances assigned to static final variables. The registration of dependency performed by Manage class.
class AppModule extends Module {
AppModule() : super({});
static final service = Manage(Service.new);
}
copied to clipboard
The full code of new Manage instance look like this:
class AppModule extends Module {
AppModule() : super({});
static final service = Manage<RegistrationType>(
ServiceFactory,
scope: Scope.unique,
dependsOn: [],
);
}
copied to clipboard
In example above you can see some optional parameters. Parameter scope used
to provide specific scope in which instance of dependency will be managed.
Parameter dependsOn used to initialize registration of other dependencies
necessary for this dependency.
You should keep in mind that value of static variables initialized on first
use. This means that until you access the variable its value will not be
created. Thats why we should use other static variables in dependsOn
parameter.
The factory you provide at construction of Manage instance can be class
constructor
Manage(Service.new);
copied to clipboard
or you can provide closure
Manage(() => Service());
copied to clipboard
In simple cases the generic type for Manage instance will be inferred
automatically. But in some cases you should define generic parameter
explicitly.
Manage<Service>(() => Service());
copied to clipboard
Use some static variables in super constructor
class AppModule extends Module {
AppModule() : super({service});
static final service = Manage(Service.new, dependsOn: [client]);
static final client = Manage(HttpClient.new);
}
copied to clipboard
This step is necessary because some static variables may not be initialized.
This is necessary only for those variables that have not been used anywhere else.
In real code, we usually encounter a situation where some dependencies
depend on others. In our case, accessing variables in the constructor that
no one has referred to yet will lead to initialization of the values of
these variables and the entire graph of variables on which it depends.
In example above when we use service variable in constructor its value
will be created and also will be created value for client variable.
Scopes #
Scope is a mechanism which help control injection behaviour. This library
provide three different implementation of Scope
unique - create new instance every time
singleton - create new instance only once and instance will never be dropped
cached - create new instance and store it until reset. When reset
method called than previously created instances will be dropped.
Every instance provided from scope created by factory provided at
construction of Manage instance. If you use cached or singleton scope
than instances provided from scope will be stored in pair with its factory.
This allows us to make registration with different type and same factory and
at the time of access same instance will be shared with different types
Mix Managed mixin where you wnt to use dependency
class Service with Managed {
}
copied to clipboard
The Managed mixin redefine noSuchMethod to implement injection behaviour
(See mixin implementation for more details).
Define provider method to inject dependency
class Service with Managed {
T _httpClient<T extends HttpClient>();
}
copied to clipboard
In example below we define method with generic parameter T which should
extend HttpClient and without method body. Such declaration at runtime will
delegate all invocation to noSuchMethod where we have access to
invocation details via Invocation class. The invocation class contains
information about concrete values of generic parameters at the moment of
call. In our example value of generic parameter will be HttpClient because we
bound generic parameter by concrete type it must implement. And because we
not specify generic parameter at the moment of call the value of parameter
become equal to bounded type. And because we have concrete dependency type
from generic parameter value we can find Manage instance with equal type
ant then get instance of type using concrete type factory and provided scope.
To provide dependency instance without Managed mixin and provider method
you can use module static variable directly.
final service = AppModule.service();
copied to clipboard
For more information about usage and implementation see source code and test.
I will be back in future with more examples.
Thank you.
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.