dartypod 0.2.0
dartypod: ^0.2.0 copied to clipboard
A minimal Service Locator with compile-time safe provider references, enabling clean dependency injection patterns.
dartypod #
A minimal Service Locator with compile-time safe provider references, enabling clean dependency injection patterns in Dart.
Dartypod provides compile-time safe dependency injection through provider references rather than runtime type lookup.
Features #
- Zero dependencies - No external runtime dependencies
- Compile-time safety - Provider references instead of runtime type lookup
- Flexible scoping - Singleton, transient, and custom hierarchical scopes
- Easy testing - Built-in override support for mocking
- Automatic disposal - Supports
Disposableinterface and custom dispose callbacks
Installation #
Add to your pubspec.yaml:
dependencies:
dartypod: ^0.1.0
Then run:
dart pub get
Usage #
Define Providers #
import 'package:dartypod/dartypod.dart';
// Simple provider (singleton by default)
final httpClientProvider = Provider<HttpClient>(
(_) => HttpClientImpl(),
);
// Provider with dependency
final apiServiceProvider = Provider<ApiService>(
(pod) => ApiServiceImpl(
client: pod.resolve(httpClientProvider),
),
);
Resolve Dependencies #
void main() {
final pod = Pod();
final apiService = pod.resolve(apiServiceProvider);
// Use apiService...
// Don't forget to dispose when done
pod.dispose();
}
Scopes #
Singleton (default)
Instances are cached and reused:
final provider = Provider<MyService>((pod) => MyService());
// Same instance returned every time
Transient
New instance created every time:
final provider = Provider<MyService>(
(pod) => MyService(),
scope: const TransientScope(),
);
// Different instance each time
Custom Scopes
Create hierarchical scopes for advanced use cases:
const sessionScope = CustomScope('session');
const requestScope = CustomScope('request', parent: sessionScope);
final sessionProvider = Provider<SessionData>(
(pod) => SessionData(),
scope: sessionScope,
);
// Clear a scope (also clears child scopes)
pod.clearScope(sessionScope);
Testing with Overrides #
void main() {
final pod = Pod();
// Override with mock
pod.overrideProvider(httpClientProvider, (_) => MockHttpClient());
// Now apiService uses MockHttpClient
final apiService = pod.resolve(apiServiceProvider);
// Remove override to restore original
pod.removeOverride(httpClientProvider);
}
Disposal #
Implement Disposable for automatic cleanup:
class MyService implements Disposable {
@override
void dispose() {
// Cleanup resources
}
}
Or provide a custom dispose callback:
final provider = Provider<MyService>(
(pod) => MyService(),
dispose: (instance) => instance.close(),
);
Call pod.dispose() to clean up all cached instances.
API Reference #
Pod #
resolve<T>(Provider<T> provider)- Get instance from provideroverrideProvider<T>(provider, builder)- Override for testingremoveOverride<T>(provider)- Remove overrideclearScope(scope)- Clear cached instances for scopedispose()- Dispose all cached instances
Provider #
Provider(builder, {scope, dispose})- Create a providerbuild(pod)- Build new instance (used internally)disposeInstance(instance)- Dispose instance (used internally)
ProviderScope #
SingletonScope- Cache and reuse (default)TransientScope- Always create newCustomScope(name, {parent})- Custom with optional hierarchy
Contributing #
Contributions are welcome! See CONTRIBUTING.md for how to get started.
License #
MIT