levit_scope 0.0.4
levit_scope: ^0.0.4 copied to clipboard
Pure Dart dependency injection and service locator. Part of the Levit framework.
levit_scope #
Type-safe, hierarchical dependency injection for Dart. Explicit. Scoped. Deterministic.
levit_scope is a pure Dart dependency injection and service locator designed for applications requiring predictable lifecycles and explicit scoping. It provides a robust, reflection-free mechanism for managing services and controllers across the Levit ecosystem.
Purpose & Scope #
levit_scope provides the container infrastructure for the Levit framework. Its primary responsibilities include:
- Managing a registry of typed dependencies with optional tagging.
- Enforcing hierarchical isolation between different layers of the application.
- Orchestrating lifecycle hooks (
onInit,onClose) for managed components.
By maintaining a pure Dart profile, it ensures that your dependency graph remains testable and portable across CLI, server, and multi-platform environments.
Conceptual Overview #
Core Abstractions #
LevitScope: A container that holds dependency registrations. Scopes can be nested to form a tree.LevitScopeDisposable: An interface that allows components to react to their own initialization and disposal.- Ambient Scoping: While
levit_scopeis the low-level engine, it is often used via the ambientLevitinterface inlevit_dartfor boilerplate-free resolution.
Getting Started #
Hierarchical Scoping #
// Create a root scope
final root = LevitScope.root();
// Register a singleton
root.put(() => AuthService());
// Create a child scope for a specific feature
final featureScope = root.createScope('payment_flow');
featureScope.put(() => PaymentProcessor());
// Resolve from child (falls back to parent)
final auth = featureScope.find<AuthService>();
Lifecycle Hooks #
Implement LevitScopeDisposable to manage resources:
class Database implements LevitScopeDisposable {
@override
void onInit() => print('Connecting...');
@override
void onClose() => print('Closing connection...');
}
Design Principles #
Explicitness over Magic #
There is no hidden reflection or code generation. Every dependency is registered and resolved via typed builder functions.
Deterministic Teardown #
When a scope is disposed, every disposable dependency it owns is guaranteed to have its onClose method called. This is critical for preventing memory leaks in complex applications.
Isolation #
Child scopes can override parent dependencies locally. This enables powerful testing patterns where you can "mock" a dependency for a specific subtree of your application without affecting the global state.