unregister<T extends Object> method
Unregisters a dependency.
Honors the documented contract:
- If
traverseisfalse, parents are not walked. Only this container is touched. - If
removeAllistrue(the default), the dependency is removed from this container and every parent that has a matching registration. Whenfalse, only the first matching registration (this-first, parent-walk thereafter) is removed. - If
triggerOnUnregisterCallbacksistrue, every removed dependency'sonUnregistercallback fires (sequentially, in container-walk order). Returns once all callbacks have completed.
The returned Option<T> is the value of the first removed dependency
(or None if nothing was removed).
Implementation
Resolvable<Option<T>> unregister<T extends Object>({
Entity groupEntity = const DefaultEntity(),
bool traverse = true,
bool removeAll = true,
bool triggerOnUnregisterCallbacks = true,
}) {
assert(T != Object, 'T must be specified and cannot be Object.');
final g = groupEntity.preferOverDefault(focusGroup);
final removed = <Dependency>[];
// Walk the FULL ancestor chain (with cycle detection) — not just direct
// parents — so `unregister(traverse: true, removeAll: true)` and
// `isRegistered(traverse: true)` agree on which deps exist. Previously
// `unregister` only touched `this` and direct parents, so a grandparent
// registration that `isRegistered` could see would survive a deep
// unregister — a real reliability hole on three-level hierarchies.
final containers = traverse ? _allAncestors() : <DI>[this as DI];
walk:
for (final di in containers) {
switch (di.removeDependency<T>(groupEntity: g)) {
case Some(value: final dep):
removed.add(dep);
// Clean up any pending untilExactlyK completers for this type.
// The cast is guarded because DIBase itself does NOT require
// SupportsMixinK — only the concrete `DI` mixes it in.
(di as SupportsMixinK).cleanupCompleters(
TypeEntity(T),
groupEntity: g,
);
if (!removeAll) break walk;
case None():
if (!removeAll) break walk;
}
}
if (removed.isEmpty) return Sync.okValue(None<T>());
return _runOnUnregisterChain<T>(
removed: removed,
triggerOnUnregisterCallbacks: triggerOnUnregisterCallbacks,
);
}