mirror of
https://github.com/pese-git/cherrypick.git
synced 2026-01-24 05:25:19 +00:00
docs(di): clarify 'toInstance' binding limitations in builder
- Add explicit note for users about the impossibility to use scope.resolve<T>() for just-to-be-registered types inside Module.builder when registering chained dependencies via toInstance. - Show correct and incorrect usage patterns, functional and anti-pattern Dart examples in RU and EN full tutorials. - Add the warning to the main README after core concept bindings block, improving discoverability for users starting with the library. - Motivation: Prevent common misuse and hard-to-debug runtime errors for users who construct chains using toInstance/resolve inside the builder.
This commit is contained in:
@@ -44,6 +44,46 @@ final setupFuture = loadEnvironment();
|
||||
bind<Environment>().toInstanceAsync(setupFuture);
|
||||
```
|
||||
|
||||
> ⚠️ **Important note about using toInstance in Module**
|
||||
>
|
||||
> If you register a chain of dependencies via `toInstance` inside the `builder` method of your `Module`, you must NOT call `scope.resolve<T>()` for a type that you have just bound—at this moment.
|
||||
>
|
||||
> CherryPick initializes all bindings inside `builder` sequentially: at the time of a new binding, not all other dependencies are registered yet in the DI container. If you try to use `scope.resolve<T>()` for an object you have just added in the same `builder`, it will result in an error (`Can't resolve dependency ...`).
|
||||
>
|
||||
> **Correct way:**
|
||||
> Manually construct the entire object chain before registering:
|
||||
>
|
||||
> ```dart
|
||||
> void builder(Scope scope) {
|
||||
> final a = A();
|
||||
> final b = B(a);
|
||||
> final c = C(b);
|
||||
> bind<A>().toInstance(a);
|
||||
> bind<B>().toInstance(b);
|
||||
> bind<C>().toInstance(c);
|
||||
> }
|
||||
> ```
|
||||
>
|
||||
> **Incorrect:**
|
||||
> ```dart
|
||||
> void builder(Scope scope) {
|
||||
> bind<A>().toInstance(A());
|
||||
> // Error! At this point, A is not registered yet.
|
||||
> bind<B>().toInstance(B(scope.resolve<A>()));
|
||||
> }
|
||||
> ```
|
||||
>
|
||||
> **Incorrect:**
|
||||
> ```dart
|
||||
> void builder(Scope scope) {
|
||||
> bind<A>().toProvide(() => A());
|
||||
> // Error! At this point, A is not registered yet.
|
||||
> bind<B>().toInstance(B(scope.resolve<A>()));
|
||||
> }
|
||||
> ```
|
||||
>
|
||||
> **Note:** This limitation applies only to `toInstance`. For providers (`toProvide`/`toProvideAsync`) and other strategies, you can freely use `scope.resolve<T>()` inside `builder`.
|
||||
|
||||
- **toProvide** — regular sync factory
|
||||
- **toProvideAsync** — async factory (if you need to await a Future)
|
||||
- **toProvideWithParams / toProvideAsyncWithParams** — factories with runtime parameters
|
||||
|
||||
Reference in New Issue
Block a user