Line data Source code
1 : library klizma;
2 :
3 : import 'package:klizma/src/provider.dart';
4 : import 'package:klizma/src/singleton.dart';
5 :
6 : /// This is a Dependency Injection container.
7 : /// Use it as is or inherit from [KlizmaMixin] to extend functionality.
8 : class Klizma with KlizmaMixin {
9 : /// A shortcut for `get()`.
10 0 : T call<T extends Object>([String name = '']) => get<T>(name);
11 : }
12 :
13 : /// This is the implementation of the Dependency Injection container.
14 : mixin KlizmaMixin {
15 : final _providers = <int, Map<String, Provider>>{};
16 :
17 : /// Adds a service [factory] of type [T] to the container.
18 : /// Specify [name] to have several (named) factories of the same type.
19 : /// By default, all services are singletons. Set [cached] to `false`
20 : /// to get a new instance each time the service is requested.
21 : ///
22 : /// Throws [StateError] if the service factory is already registered.
23 1 : void add<T extends Object>(T Function() factory,
24 : {String name = '', bool cached = true}) {
25 4 : final map = (_providers[T.hashCode] ??= <String, Provider<T>>{});
26 1 : if (map.containsKey(name)) {
27 1 : throw StateError('Service already exists');
28 : }
29 1 : final provider = Provider<T>(factory);
30 2 : map[name] = cached ? Singleton<T>(provider) : provider;
31 : }
32 :
33 : /// Returns the service instance for type [T].
34 : /// Specify [name] to get the named instance.
35 : ///
36 : /// Throws [StateError] if the service is not found.
37 3 : T get<T extends Object>([String name = '']) => _provider<T>(name).get();
38 :
39 : /// Returns the service instance for type [T] if it has already been instantiated.
40 : /// Provide [name] to get the named instance.
41 : ///
42 : /// Throws [StateError] if the service is not found.
43 1 : T? getCached<T extends Object>([String name = '']) {
44 1 : final provider = _provider<T>(name);
45 1 : if (provider is Singleton<T>) {
46 1 : return provider.getCached();
47 : }
48 : }
49 :
50 1 : Provider<T> _provider<T extends Object>(String name) =>
51 5 : (_providers[T.hashCode]?[name] ?? (throw StateError('Service not found')))
52 : as Provider<T>;
53 : }
|