0 purchases
dep gen
DepGen #
In short, this package allows you to implement dependency injection in a project.
Features #
This package lets you generate special methods which create instances of classes with automatic
substitution of dependencies from the environment. Looking ahead, we can immediately show what such
methods do:
Instead of specifying dependencies manually:
// Some example class with dependencies
class MyPet{
MyPet({
required String name,
required PetsRepository petsRepository,
required ShopRepository shopRepository,
}) {
… some magic…
}
}
void main() {
…
final pet = MyPet(
name: 'Lucky',
petsRepository: context.read<PetsRepository>(),
shopRepository: context.read<ShopRepository>(),
);
…
}
copied to clipboard
You won’t have to worry about delivering dependencies and just call a special method, specifying the
missing parameters (if any):
@DepGen()
class MyPet{
MyPet({
required String name,
@DepArg() required PetsRepository petsRepository,
@DepArg() required ShopRepository shopRepository,
}) {
… some magic…
}
}
void main() {
…
final pet = context.depGen().buildMyPet(name: 'Lucky');
…
}
copied to clipboard
How to start #
Steps to get started
Import the package
Annotations placement
Code generation
Description of the environment
Integration into widget hierarchy
Using build methods
Some of these steps are performed only once during the design phase, so using this package should
not cause any inconvenience
Import the package #
With Dart:
dart pub add dep_gen
copied to clipboard
With Flutter:
flutter pub add dep_gen
copied to clipboard
Annotations placement #
To perform code generation, special annotations are used - @DepGen and @DepArg. The
first (DepGen) annotation is used to indicate the class for which the build method will be
created. The second annotation (DepArg) serves to indicate which dependencies need to be
substituted automatically.
💡 Annotations in Dart are a way of adding metadata to code elements such as classes, methods, variables, and parameters. Annotations are used to provide additional information about the code element, such as its intended use, expected behavior, or implementation details.
Dart annotations are represented using the '@' symbol followed by the name of the annotation.
Example code
@DepGen()
class MyPet{
MyPet({
required String name,
@DepArg() required PetsRepository petsRepository,
@DepArg() required ShopRepository shopRepository,
}) {
… some magic…
}
}
copied to clipboard
❗️ Important. Only named parameters can be marked with this annotation
This example uses two dependencies petsRepository and shopRepository to construct an instance of
the class. Let's mark them with a special @DepArg annotation so that we can generate a constructor
for an instance of this class without explicitly specifying these parameters. The class itself must
also be marked with the @DepGen annotation. That's all, we just added three words.
Code generation #
Run code generator from project directory.
flutter pub run dep_gen:generate -p lib/domain/environment
copied to clipboard
On the command line, as a parameter, we specify the path to the file that will be generated:
-p lib/domain/environment
By default the generated file will be named:
builders.dep_gen.dart
💡 To convenience, the command to run code generation can be bound, since to create new or change old build methods you need to run it again (as is any case where code generation is used).
At this stage, everything is ready - we have generated code that allows us to describe the
environment and create instances of classes with automatic substitution of dependencies.
Description of the environment #
Those instances of classes that will be substituted as dependencies cannot come from nowhere. We
need to describe the so-called environment in which instances of these classes will be registered.
The file generated in the previous step contains the DepGenEnvironment class, which allows you to
register the necessary dependencies. For this he has a special method:
void registry<T>(Object instance)
copied to clipboard
If you need to lock your environment settings, there is a special method for this. It creates a new
instance of the environment.
DepGenEnvironment lock()
copied to clipboard
A simple way to describe the environment. This code is usually used before the runApp in main()
method
void main() {
...
final environment = DepGenEnvironment();
environment.registry<PetsRepository>(PetsRepository());
environment.registry<ShopRepository>(ShopRepository());
...
runApp(...);
}
copied to clipboard
❕ In the example, for simplicity, the Dependency Inversion Principle is ignored
💡 To keep the code clean, you can also extend the DepGenEnvironment class and place the entire implementation of the environment logic into it. There is a code example in the package description.
Integration into widget hierarchy #
To be able to use the generated methods using the context, you need to embed the DepProvider
instance into the widget hierarchy.
void main() {
...
final environment = DepGenEnvironment();
environment.registry<PetsRepository>(PetsRepository());
environment.registry<ShopRepository>(ShopRepository());
...
runApp(DepProvider(
environment: environment,
child: Application(),
));
}
copied to clipboard
That's all, now you can use build methods to create class instances.
Using build methods #
To create instances of classes with injected dependencies, we need context. There are two ways:
final myPetLucky = DepProvider.of(context).buildMyPet(name: 'Lucky');
copied to clipboard
final myPetChester = context.depGen().buildMyPet(name: 'Lucky');
copied to clipboard
🔥 Congratulations, you have added dependency injection to your project.
Example of parameter combination #
You can combine positional, named, and optional arguments together with automatically substituted
arguments. For example, for a constructor that has this set of parameters:
@DepGen()
class UserDetails {
const UserDetails(final int id,
String? username, {
@DepArg() required this.api,
int? userGroup,
@DepArg() required this.cartRepository,
@DepArg() StoreRepository storeRepository,
}) :_storeRepository = storeRepository;
}
copied to clipboard
This build method will be generated:
{
DepProvider.of(context).buildUserDetails(
id,
username,
userGroup: userGroup,
)
}
copied to clipboard
Other parameters marked with a special annotation will be substituted automatically from the
environment.
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.