mirror of
https://github.com/pese-git/cherrypick.git
synced 2026-01-23 21:13:35 +00:00
docs+feat: add Disposable interface source and usage example
feat(core,doc): unified async dispose mechanism for resource cleanup BREAKING CHANGE: - Added full support for asynchronous resource cleanup via a unified FutureOr<void> dispose() method in the Disposable interface. - The Scope now provides only Future<void> dispose() for disposing all tracked resources and child scopes (sync-only dispose() was removed). - All calls to cleanup in code and tests (scope itself, subscopes, and custom modules) now require await ...dispose(). - Documentation and all examples updated: resource management is always async and must be awaited; Disposable implementers may use both sync and async cleanup. - Old-style, synchronous cleanup methods have been completely removed (API is now consistently async for all DI lifecycle management). - Example and tutorial code now demonstrate async resource disposal patterns.
This commit is contained in:
@@ -185,6 +185,41 @@ final service = scope.tryResolve<OptionalService>(); // returns null if not exis
|
||||
---
|
||||
|
||||
|
||||
## Automatic resource management: Disposable and dispose
|
||||
|
||||
CherryPick makes it easy to clean up resources for your singleton services and other objects registered in DI.
|
||||
If your class implements the `Disposable` interface, always **await** `scope.dispose()` (or `CherryPick.closeRootScope()`) when you want to free all resources in your scope — CherryPick will automatically await `dispose()` for every object that implements `Disposable` and was resolved via DI.
|
||||
This ensures safe and graceful resource management (including any async resource cleanup: streams, DB connections, sockets, etc.).
|
||||
|
||||
### Example
|
||||
|
||||
```dart
|
||||
class LoggingService implements Disposable {
|
||||
@override
|
||||
FutureOr<void> dispose() async {
|
||||
// Close files, streams, and perform async cleanup here.
|
||||
print('LoggingService disposed!');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> main() async {
|
||||
final scope = openRootScope();
|
||||
scope.installModules([
|
||||
_LoggingModule(),
|
||||
]);
|
||||
final logger = scope.resolve<LoggingService>();
|
||||
// Use logger...
|
||||
await scope.dispose(); // prints: LoggingService disposed!
|
||||
}
|
||||
|
||||
class _LoggingModule extends Module {
|
||||
@override
|
||||
void builder(Scope scope) {
|
||||
bind<LoggingService>().toProvide(() => LoggingService()).singleton();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Dependency injection with annotations & code generation
|
||||
|
||||
CherryPick supports DI with annotations, letting you eliminate manual DI setup.
|
||||
|
||||
@@ -185,6 +185,41 @@ final service = scope.tryResolve<OptionalService>(); // вернет null, ес
|
||||
|
||||
---
|
||||
|
||||
## Автоматическое управление ресурсами: Disposable и dispose
|
||||
|
||||
CherryPick позволяет автоматически очищать ресурсы для ваших синглтонов и любых сервисов, зарегистрированных через DI.
|
||||
Если ваш класс реализует интерфейс `Disposable`, всегда вызывайте и **await**-те `scope.dispose()` (или `CherryPick.closeRootScope()`), когда хотите освободить все ресурсы — CherryPick дождётся завершения `dispose()` для всех объектов, которые реализуют Disposable и были резолвлены из DI.
|
||||
Это позволяет избежать утечек памяти, корректно завершать процессы и грамотно освобождать любые ресурсы (файлы, потоки, соединения и т.д., включая async).
|
||||
|
||||
### Пример
|
||||
|
||||
```dart
|
||||
class LoggingService implements Disposable {
|
||||
@override
|
||||
FutureOr<void> dispose() async {
|
||||
// Закрыть файлы, потоки, соединения и т.д. (можно с await)
|
||||
print('LoggingService disposed!');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> main() async {
|
||||
final scope = openRootScope();
|
||||
scope.installModules([
|
||||
_LoggingModule(),
|
||||
]);
|
||||
final logger = scope.resolve<LoggingService>();
|
||||
// Используем logger...
|
||||
await scope.dispose(); // выведет: LoggingService disposed!
|
||||
}
|
||||
|
||||
class _LoggingModule extends Module {
|
||||
@override
|
||||
void builder(Scope scope) {
|
||||
bind<LoggingService>().toProvide(() => LoggingService()).singleton();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Внедрение зависимостей через аннотации и автогенерацию
|
||||
|
||||
CherryPick поддерживает DI через аннотации, что позволяет полностью избавиться от ручного внедрения зависимостей.
|
||||
|
||||
@@ -75,8 +75,54 @@ Example:
|
||||
// or
|
||||
final str = rootScope.tryResolve<String>();
|
||||
|
||||
// close main scope
|
||||
Cherrypick.closeRootScope();
|
||||
// Recommended: Close the root scope & automatically release all Disposable resources
|
||||
await Cherrypick.closeRootScope();
|
||||
// Or, for advanced/manual scenarios:
|
||||
// await rootScope.dispose();
|
||||
```
|
||||
|
||||
### Automatic resource management (`Disposable`, `dispose`)
|
||||
|
||||
If your service implements the `Disposable` interface, CherryPick will automatically await `dispose()` when you close a scope.
|
||||
|
||||
**Best practice:**
|
||||
Always finish your work with `await Cherrypick.closeRootScope()` (for the root scope) or `await scope.closeSubScope('feature')` (for subscopes).
|
||||
These methods will automatically await `dispose()` on all resolved objects implementing `Disposable`, ensuring safe and complete cleanup (sync and async).
|
||||
|
||||
Manual `await scope.dispose()` is available if you manage scopes yourself.
|
||||
|
||||
#### Example
|
||||
|
||||
```dart
|
||||
class MyService implements Disposable {
|
||||
@override
|
||||
FutureOr<void> dispose() async {
|
||||
// release resources, close connections, perform async shutdown, etc.
|
||||
print('MyService disposed!');
|
||||
}
|
||||
}
|
||||
|
||||
final scope = openRootScope();
|
||||
scope.installModules([
|
||||
ModuleImpl(),
|
||||
]);
|
||||
|
||||
final service = scope.resolve<MyService>();
|
||||
|
||||
// ... use service
|
||||
|
||||
// Recommended:
|
||||
await Cherrypick.closeRootScope(); // will print: MyService disposed!
|
||||
|
||||
// Or, to close a subscope:
|
||||
await scope.closeSubScope('feature');
|
||||
|
||||
class ModuleImpl extends Module {
|
||||
@override
|
||||
void builder(Scope scope) {
|
||||
bind<MyService>().toProvide(() => MyService()).singleton();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Logging
|
||||
|
||||
@@ -75,8 +75,54 @@ Scope - это контейнер, который хранит все дерев
|
||||
// или
|
||||
final str = rootScope.tryResolve<String>();
|
||||
|
||||
// закрыть главный scope
|
||||
Cherrypick.closeRootScope();
|
||||
// Рекомендуется: закрывайте главный scope для автоматического освобождения всех ресурсов
|
||||
await Cherrypick.closeRootScope();
|
||||
// Или, для продвинутых/ручных сценариев:
|
||||
// await rootScope.dispose();
|
||||
```
|
||||
|
||||
### Автоматическое управление ресурсами (`Disposable`, `dispose`)
|
||||
|
||||
Если ваш сервис реализует интерфейс `Disposable`, CherryPick автоматически дождётся выполнения `dispose()` при закрытии scope.
|
||||
|
||||
**Рекомендация:**
|
||||
Завершайте работу через `await Cherrypick.closeRootScope()` (для root scope) или `await scope.closeSubScope('feature')` (для подскоупов).
|
||||
Эти методы автоматически await-ят `dispose()` для всех разрешённых через DI объектов, реализующих `Disposable`, обеспечивая корректную очистку (sync и async) и высвобождение ресурсов.
|
||||
|
||||
Вызывайте `await scope.dispose()` если вы явно управляете custom-скоупом.
|
||||
|
||||
#### Пример
|
||||
|
||||
```dart
|
||||
class MyService implements Disposable {
|
||||
@override
|
||||
FutureOr<void> dispose() async {
|
||||
// закрытие ресурса, соединений, таймеров и т.п., async/await
|
||||
print('MyService disposed!');
|
||||
}
|
||||
}
|
||||
|
||||
final scope = openRootScope();
|
||||
scope.installModules([
|
||||
ModuleImpl(),
|
||||
]);
|
||||
|
||||
final service = scope.resolve<MyService>();
|
||||
|
||||
// ... используем сервис ...
|
||||
|
||||
// Рекомендуемый финал:
|
||||
await Cherrypick.closeRootScope(); // выведет в консоль 'MyService disposed!'
|
||||
|
||||
// Или для подскоупа:
|
||||
await scope.closeSubScope('feature');
|
||||
|
||||
class ModuleImpl extends Module {
|
||||
@override
|
||||
void builder(Scope scope) {
|
||||
bind<MyService>().toProvide(() => MyService()).singleton();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Логирование
|
||||
|
||||
Reference in New Issue
Block a user