mirror of
https://github.com/pese-git/cherrypick.git
synced 2026-01-23 21:13:35 +00:00
docs: add annotation usage guides (en, ru) with up-to-date examples and best practices
This commit is contained in:
140
doc/annotations_en.md
Normal file
140
doc/annotations_en.md
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
# DI Code Generation with Annotations (CherryPick)
|
||||||
|
|
||||||
|
CherryPick enables smart, fully-automated dependency injection (DI) for Dart/Flutter via annotations and code generation.
|
||||||
|
This eliminates boilerplate and guarantees correctness—just annotate, run the generator, and use!
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. How does it work?
|
||||||
|
|
||||||
|
You annotate classes, fields, and modules using [cherrypick_annotations].
|
||||||
|
The [cherrypick_generator] processes these, generating code that registers your dependencies and wires up fields or modules.
|
||||||
|
|
||||||
|
You then run:
|
||||||
|
```sh
|
||||||
|
dart run build_runner build --delete-conflicting-outputs
|
||||||
|
```
|
||||||
|
— and use the generated files in your app.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Supported Annotations
|
||||||
|
|
||||||
|
| Annotation | Where | Purpose |
|
||||||
|
|-------------------|-----------------|----------------------------------------------------------|
|
||||||
|
| `@injectable()` | class | Enables auto field injection; mixin will be generated |
|
||||||
|
| `@inject()` | field | Field will be injected automatically |
|
||||||
|
| `@scope()` | field/param | Use a named scope when resolving this dep |
|
||||||
|
| `@named()` | field/param | Bind/resolve a named interface implementation |
|
||||||
|
| `@module()` | class | Marks as a DI module (methods = providers) |
|
||||||
|
| `@provide` | method | Registers a type via this provider method |
|
||||||
|
| `@instance` | method | Registers a direct instance (like singleton/factory) |
|
||||||
|
| `@singleton` | method/class | The target is a singleton |
|
||||||
|
| `@params` | param | Accepts runtime/constructor params for providers |
|
||||||
|
|
||||||
|
**You can combine annotations as needed for advanced use-cases.**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Practical Examples
|
||||||
|
|
||||||
|
### A. Field Injection (recommended for widgets/classes)
|
||||||
|
|
||||||
|
```dart
|
||||||
|
import 'package:cherrypick_annotations/cherrypick_annotations.dart';
|
||||||
|
|
||||||
|
@injectable()
|
||||||
|
class MyWidget with _$MyWidget { // the generated mixin
|
||||||
|
@inject()
|
||||||
|
late final AuthService auth;
|
||||||
|
|
||||||
|
@inject()
|
||||||
|
@scope('profile')
|
||||||
|
late final ProfileManager profile;
|
||||||
|
|
||||||
|
@inject()
|
||||||
|
@named('special')
|
||||||
|
late final ApiClient specialApi;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- After running build_runner, the mixin _$MyWidget is created.
|
||||||
|
- Call `MyWidget().injectFields();` (method name may be `_inject` or similar) to populate the fields!
|
||||||
|
|
||||||
|
### B. Module Binding (recommended for global app services)
|
||||||
|
|
||||||
|
```dart
|
||||||
|
@module()
|
||||||
|
abstract class AppModule extends Module {
|
||||||
|
@singleton
|
||||||
|
AuthService provideAuth(Api api) => AuthService(api);
|
||||||
|
|
||||||
|
@provide
|
||||||
|
@named('logging')
|
||||||
|
Future<Logger> provideLogger(@params Map<String, dynamic> args) async => ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- Providers can return async(`Future<T>`) or sync.
|
||||||
|
- `@singleton` = one instance per scope.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Using the Generated Code
|
||||||
|
|
||||||
|
1. Add to your `pubspec.yaml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
dependencies:
|
||||||
|
cherrypick: any
|
||||||
|
cherrypick_annotations: any
|
||||||
|
|
||||||
|
dev_dependencies:
|
||||||
|
cherrypick_generator: any
|
||||||
|
build_runner: any
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Import generated files (e.g. `app_module.module.cherrypick.g.dart`, `your_class.inject.cherrypick.g.dart`).
|
||||||
|
|
||||||
|
3. Register modules:
|
||||||
|
|
||||||
|
```dart
|
||||||
|
final scope = openRootScope()
|
||||||
|
..installModules([$AppModule()]);
|
||||||
|
```
|
||||||
|
|
||||||
|
4. For classes with auto-injected fields, mix in the generated mixin and call the injector:
|
||||||
|
|
||||||
|
```dart
|
||||||
|
final widget = MyWidget();
|
||||||
|
widget.injectFields(); // or use the mixin's helper
|
||||||
|
```
|
||||||
|
|
||||||
|
5. All dependencies are now available and ready to use!
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Advanced Features
|
||||||
|
|
||||||
|
- **Named and Scoped dependencies:** use `@named`, `@scope` on fields/methods and in resolve().
|
||||||
|
- **Async support:** Providers or injected fields can be Future<T> (resolveAsync).
|
||||||
|
- **Runtime parameters:** Decorate a parameter with `@params`, and use `resolve<T>(params: ...)`.
|
||||||
|
- **Combining strategies:** Mix field injection (`@injectable`) and module/provider (`@module` + methods) in one app.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Troubleshooting
|
||||||
|
|
||||||
|
- Make sure all dependencies are annotated, imports are correct, and run `build_runner` on every code/DI change.
|
||||||
|
- Errors in annotation usage (e.g. `@singleton` on non-class/method) will be shown at build time.
|
||||||
|
- Use the `.g.dart` files directly—do not edit them by hand.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. References
|
||||||
|
|
||||||
|
- [Cherrypick Generator README (extended)](../cherrypick_generator/README.md)
|
||||||
|
- Example: `examples/postly`
|
||||||
|
- [API Reference](../cherrypick/doc/api/)
|
||||||
|
|
||||||
|
---
|
||||||
137
doc/annotations_ru.md
Normal file
137
doc/annotations_ru.md
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
# Генерация DI-кода через аннотации (CherryPick)
|
||||||
|
|
||||||
|
CherryPick позволяет получить умный и полностью автоматизированный DI для Dart/Flutter на основе аннотаций и генерации кода.
|
||||||
|
Это убирает boilerplate — просто ставьте аннотации, запускайте генератор и используйте результат!
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Как это работает?
|
||||||
|
|
||||||
|
Вы размечаете классы, поля и модули с помощью [cherrypick_annotations].
|
||||||
|
[cherrypick_generator] анализирует их и создаёт код для регистрации зависимостей и подстановки полей или модулей.
|
||||||
|
|
||||||
|
Далее — запускайте:
|
||||||
|
```sh
|
||||||
|
dart run build_runner build --delete-conflicting-outputs
|
||||||
|
```
|
||||||
|
— и используйте сгенерированные файлы в проекте.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Поддерживаемые аннотации
|
||||||
|
|
||||||
|
| Аннотация | Где применить | Значение |
|
||||||
|
|--------------------|------------------|------------------------------------------------------------|
|
||||||
|
| `@injectable()` | класс | Включает автоподстановку полей, генерируется mixin |
|
||||||
|
| `@inject()` | поле | Поле будет автоматически подставлено DI |
|
||||||
|
| `@scope()` | поле/параметр | Использовать определённый scope при разрешении |
|
||||||
|
| `@named()` | поле/параметр | Именованный биндинг для интерфейсов/реализаций |
|
||||||
|
| `@module()` | класс | Класс как DI-модуль (методы — провайдеры) |
|
||||||
|
| `@provide` | метод | Регистрирует тип через этот метод-провайдер |
|
||||||
|
| `@instance` | метод | Регистрирует как прямой инстанс (singleton/factory, как есть)|
|
||||||
|
| `@singleton` | метод/класс | Синглтон (один экземпляр на scope) |
|
||||||
|
| `@params` | параметр | Пробрасывает параметры рантайм/конструктора в DI |
|
||||||
|
|
||||||
|
Миксуйте аннотации для сложных сценариев!
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Примеры использования
|
||||||
|
|
||||||
|
### A. Field Injection (рекомендуется для виджетов/классов)
|
||||||
|
|
||||||
|
```dart
|
||||||
|
import 'package:cherrypick_annotations/cherrypick_annotations.dart';
|
||||||
|
|
||||||
|
@injectable()
|
||||||
|
class MyWidget with _$MyWidget {
|
||||||
|
@inject()
|
||||||
|
late final AuthService auth;
|
||||||
|
|
||||||
|
@inject()
|
||||||
|
@scope('profile')
|
||||||
|
late final ProfileManager profile;
|
||||||
|
|
||||||
|
@inject()
|
||||||
|
@named('special')
|
||||||
|
late final ApiClient specialApi;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- После build_runner появится mixin _$MyWidget.
|
||||||
|
- Вызовите `MyWidget().injectFields();` (или соответствующий метод из mixin), чтобы заполнить поля.
|
||||||
|
|
||||||
|
### B. Binding через модуль (вариант для глобальных сервисов)
|
||||||
|
|
||||||
|
```dart
|
||||||
|
@module()
|
||||||
|
abstract class AppModule extends Module {
|
||||||
|
@singleton
|
||||||
|
AuthService provideAuth(Api api) => AuthService(api);
|
||||||
|
|
||||||
|
@provide
|
||||||
|
@named('logging')
|
||||||
|
Future<Logger> provideLogger(@params Map<String, dynamic> args) async => ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- Методы-провайдеры поддерживают async (Future<T>) и singleton.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Использование сгенерированного кода
|
||||||
|
|
||||||
|
1. В `pubspec.yaml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
dependencies:
|
||||||
|
cherrypick: any
|
||||||
|
cherrypick_annotations: any
|
||||||
|
|
||||||
|
dev_dependencies:
|
||||||
|
cherrypick_generator: any
|
||||||
|
build_runner: any
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Импортируйте сгенерированные файлы (`app_module.module.cherrypick.g.dart`, `your_class.inject.cherrypick.g.dart`).
|
||||||
|
|
||||||
|
3. Регистрируйте модули так:
|
||||||
|
|
||||||
|
```dart
|
||||||
|
final scope = openRootScope()
|
||||||
|
..installModules([$AppModule()]);
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Для классов с автоподстановкой полей (field injection): используйте mixin и вызовите injector:
|
||||||
|
|
||||||
|
```dart
|
||||||
|
final widget = MyWidget();
|
||||||
|
widget.injectFields(); // или эквивалентный метод из mixin
|
||||||
|
```
|
||||||
|
|
||||||
|
5. Все зависимости готовы к использованию!
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Расширенные возможности
|
||||||
|
|
||||||
|
- **Именованные и scope-зависимости:** используйте `@named`, `@scope` в полях/методах/resolve.
|
||||||
|
- **Async:** Провайдеры и поля могут быть Future<T> (resolveAsync).
|
||||||
|
- **Параметры рантайм:** через `@params` прямо к провайдеру: `resolve<T>(params: ...)`.
|
||||||
|
- **Комбинированная стратегия:** можно смешивать field injection и модульные провайдеры в одном проекте.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Советы и FAQ
|
||||||
|
|
||||||
|
- Проверьте аннотации, пути import и запускайте build_runner после каждого изменения DI/кода.
|
||||||
|
- Ошибки применения аннотаций появляются на этапе генерации.
|
||||||
|
- Никогда не редактируйте .g.dart файлы вручную.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Полезные ссылки
|
||||||
|
|
||||||
|
- [README по генератору](../cherrypick_generator/README.md)
|
||||||
|
- Пример интеграции: `examples/postly`
|
||||||
|
- [API Reference](../cherrypick/doc/api/)
|
||||||
|
|
||||||
|
---
|
||||||
Reference in New Issue
Block a user