singleton_manager 2.0.0
singleton_manager: ^2.0.0 copied to clipboard
High-performance singleton manager for Dart with DI annotations and lazy loading.
singleton_manager #
A minimal, zero-dependency dependency-injection registry for Dart:
RegistryManager, the IRegistry interface it implements, and the
@dependencyInjectable annotation used by
singleton_manager_generator to write
factory constructors for you.
Features #
- Type-safe: generic
getInstance<T>()/connectInstance<Interface, Impl>() - Zero dependencies: no external package dependencies at runtime
- Lazy: a connected factory runs once, the first time its type is resolved; the result is then cached
- Per-key registration: register multiple instances of the same type under different string keys (default key:
'default') - Code generation ready: annotate a class with
@dependencyInjectable, let the generator write itsdependencyInjectionFactory() - Pure Dart: no platform-specific code, works on VM, Web, and Flutter
Installation #
Add to your pubspec.yaml:
dependencies:
singleton_manager: ^2.0.0
Quick Start #
import 'package:singleton_manager/singleton_manager.dart';
abstract class ILogger {
void log(String message);
}
class ConsoleLogger implements ILogger {
@override
void log(String message) => print(message);
}
void main() {
final registry = RegistryManager.instance;
// Connect an interface to a factory — invoked lazily, once, on first access.
registry.connectInstance<ILogger, ConsoleLogger>(() => ConsoleLogger());
// Resolve it (same cached instance every time after the first call).
final logger = registry.getInstance<ILogger>();
logger.log('Hello from ConsoleLogger!');
}
The IRegistry API #
abstract class IRegistry {
/// Returns the instance connected to [InterfaceType] under [key], creating
/// it via its connected factory on first access. Throws
/// `RegistryNotFoundError` if nothing is connected.
InterfaceType getInstance<InterfaceType>({String key = 'default'});
/// Same as [getInstance] but returns `null` instead of throwing.
InterfaceType? getInstanceNullable<InterfaceType>({String key = 'default'});
/// Connects [InterfaceType] to a concrete [InstanceType] via [factory].
/// The factory runs once, the first time [getInstance] (or
/// [getInstanceNullable]) is called for this (type, key) pair; the result
/// is cached and reused after that.
void connectInstance<InterfaceType, InstanceType extends InterfaceType>(
InstanceType Function() factory, {
String key = 'default',
});
}
RegistryManager is a singleton implementation of IRegistry, accessed via
RegistryManager.instance.
Per-key registration #
Use key to keep more than one instance of the same type — e.g.
environment-specific connections:
final registry = RegistryManager.instance;
registry.connectInstance<IDbConnection, PostgresConnection>(
() => PostgresConnection('postgres://prod'),
key: 'prod',
);
registry.connectInstance<IDbConnection, PostgresConnection>(
() => PostgresConnection('postgres://dev'),
key: 'dev',
);
final prod = registry.getInstance<IDbConnection>(key: 'prod');
final dev = registry.getInstance<IDbConnection>(key: 'dev');
Error handling #
| Situation | Result |
|---|---|
getInstance<T>() and nothing was connected/set for (T, key) |
throws RegistryNotFoundError |
getInstanceNullable<T>() and nothing was connected/set for (T, key) |
returns null |
Code generation with @dependencyInjectable #
Annotate a class and run singleton_manager_generator to have its
dependencyInjectionFactory() written for you, instead of hand-writing the
constructor call and its RegistryManager lookups:
@dependencyInjectable
class OrderService implements IOrderService {
OrderService(this._repository, {IClock? clock});
final IOrderRepository _repository;
}
See singleton_manager_generator
for how the generator maps constructor parameters to getInstance/
getInstanceNullable calls, and for the --registry-output flag that also
generates a registerAllSingletons() wiring function.
Examples #
See the examples directory for complete, runnable examples:
- 1_basic_registry.dart:
RegistryManager,connectInstance,getInstance,getInstanceNullable - 2_dependency_injection_factory.dart:
@dependencyInjectableand the generateddependencyInjectionFactory()
cd packages/singleton_manager
dart run example/1_basic_registry.dart
dart run example/2_dependency_injection_factory.dart
Documentation #
For more information, see the main project documentation.
Contributing #
See CONTRIBUTING.md for contribution guidelines.
License #
MIT License - see LICENSE file for details.