diff --git a/CHANGELOG.md b/CHANGELOG.md index 660fd37..8a57626 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## [8.0.0] - 07.05.2024 +* `getAll()` and `getAllAsync()` not have a `fromAllScopes` parameter. +* adding safeguards according to https://github.com/fluttercommunity/get_it/issues/364 to make it impossilble to call `push/popScope` while the `init()` function of another pushScope is running. +* fixed an usafe type check when using a runtime type to acess an object in get_it. ## [7.7.0] - 15.04.2024 thanks to the PR by @kasefuchs https://github.com/fluttercommunity/get_it/pull/361 `getAll` is now available in an async version too. ## [7.6.9] - 11.04.2024 * fig for bug that was introduced in 7.6.8 https://github.com/fluttercommunity/get_it/issues/358 diff --git a/lib/get_it.dart b/lib/get_it.dart index 7d0a4ea..b35309e 100644 --- a/lib/get_it.dart +++ b/lib/get_it.dart @@ -194,18 +194,21 @@ abstract class GetIt { /// The returned `Iterable` will then contain all registered instances of the requested interface [T] with or without an instance name. /// if the registrations are factories they will each be called with the provided parameters [param1,param2] and /// the results will be returned in the Iterable. + /// [fromAllScopes] if `true` it will return all instances from all scopes otherwise only from the current scope Iterable getAll({ dynamic param1, dynamic param2, + bool fromAllScopes = false, }); /// The returned `Future` will then contain all registered async registrations of the requested interface [T] with or without an instance name. /// if the registrations are factories they will each be called with the provided parameters [param1,param2] and /// the results will be returned in the Iterable. - /// + /// [fromAllScopes] if `true` it will return all instances from all scopes otherwise only from the current scope Future> getAllAsync({ dynamic param1, dynamic param2, + bool fromAllScopes = false, }); /// Callable class so that you can write `GetIt.instance` instead of diff --git a/lib/get_it_impl.dart b/lib/get_it_impl.dart index b28373f..7c155fd 100644 --- a/lib/get_it_impl.dart +++ b/lib/get_it_impl.dart @@ -355,6 +355,75 @@ class _Scope { Future dispose() async { await disposeFunc?.call(); } + + Iterable getAll({ + dynamic param1, + dynamic param2, + }) { + final _TypeRegistration? typeRegistration = + typeRegistrations[T] as _TypeRegistration?; + + if (typeRegistration == null) { + return []; + } + + final factories = [ + ...typeRegistration!.factories, + ...typeRegistration.namedFactories.values + ]; + final instances = []; + for (final instanceFactory in factories) { + final T instance; + if (instanceFactory.isAsync || instanceFactory.pendingResult != null) { + /// We use an assert here instead of an `if..throw` for performance reasons + assert( + instanceFactory.factoryType == _ServiceFactoryType.constant || + instanceFactory.factoryType == _ServiceFactoryType.lazy, + "You can't use getAll with an async Factory of $T.", + ); + throwIfNot( + instanceFactory.isReady, + StateError( + 'You tried to access an instance of $T that is not ready yet', + ), + ); + instance = instanceFactory.instance!; + } else { + instance = instanceFactory.getObject(param1, param2); + } + + instances.add(instance); + } + return instances; + } + + Future> getAllAsync({ + dynamic param1, + dynamic param2, + }) async { + final _TypeRegistration? typeRegistration = + typeRegistrations[T] as _TypeRegistration?; + + if (typeRegistration == null) { + return []; + } + + final factories = [ + ...typeRegistration!.factories, + ...typeRegistration.namedFactories.values + ]; + final instances = []; + for (final instanceFactory in factories) { + final Object instance; + if (instanceFactory.isAsync || instanceFactory.pendingResult != null) { + instance = await instanceFactory.getObjectAsync(param1, param2); + } else { + instance = instanceFactory.getObject(param1, param2); + } + instances.add(instance as T); + } + return instances; + } } class _GetItImplementation implements GetIt { @@ -496,45 +565,32 @@ class _GetItImplementation implements GetIt { Iterable getAll({ dynamic param1, dynamic param2, + bool fromAllScopes = false, }) { - final _TypeRegistration? typeRegistration = - _currentScope.typeRegistrations[T] as _TypeRegistration?; + final Iterable instances; + if (!fromAllScopes) { + instances = _currentScope.getAll( + param1: param1, + param2: param2, + ); + } else { + instances = [ + for (final scope in _scopes) + ...scope.getAll( + param1: param1, + param2: param2, + ) + ]; + } throwIf( - typeRegistration == null, + instances.isEmpty, StateError('GetIt: No Objects/factories with ' 'type $T are not registered inside GetIt. ' '\n(Did you accidentally do GetIt sl=GetIt.instance(); instead of GetIt sl=GetIt.instance;' '\nDid you forget to register it?)'), ); - final factories = [ - ...typeRegistration!.factories, - ...typeRegistration.namedFactories.values - ]; - final instances = []; - for (final instanceFactory in factories) { - final T instance; - if (instanceFactory.isAsync || instanceFactory.pendingResult != null) { - /// We use an assert here instead of an `if..throw` for performance reasons - assert( - instanceFactory.factoryType == _ServiceFactoryType.constant || - instanceFactory.factoryType == _ServiceFactoryType.lazy, - "You can't use getAll with an async Factory of $T.", - ); - throwIfNot( - instanceFactory.isReady, - StateError( - 'You tried to access an instance of $T that is not ready yet', - ), - ); - instance = instanceFactory.instance!; - } else { - instance = instanceFactory.getObject(param1, param2); - } - - instances.add(instance); - } return instances; } @@ -574,32 +630,32 @@ class _GetItImplementation implements GetIt { Future> getAllAsync({ dynamic param1, dynamic param2, + bool fromAllScopes = false, }) async { - final _TypeRegistration? typeRegistration = - _currentScope.typeRegistrations[T] as _TypeRegistration?; + final Iterable instances; + if (!fromAllScopes) { + instances = await _currentScope.getAllAsync( + param1: param1, + param2: param2, + ); + } else { + instances = [ + for (final scope in _scopes) + ...await scope.getAllAsync( + param1: param1, + param2: param2, + ) + ]; + } throwIf( - typeRegistration == null, + instances.isEmpty, StateError('GetIt: No Objects/factories with ' 'type $T are not registered inside GetIt. ' '\n(Did you accidentally do GetIt sl=GetIt.instance(); instead of GetIt sl=GetIt.instance;' '\nDid you forget to register it?)'), ); - final factories = [ - ...typeRegistration!.factories, - ...typeRegistration.namedFactories.values - ]; - final instances = []; - for (final instanceFactory in factories) { - final Object instance; - if (instanceFactory.isAsync || instanceFactory.pendingResult != null) { - instance = await instanceFactory.getObjectAsync(param1, param2); - } else { - instance = instanceFactory.getObject(param1, param2); - } - instances.add(instance as T); - } return instances; } diff --git a/pubspec.yaml b/pubspec.yaml index c89dc1e..a360dc9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: get_it description: Simple direct Service Locator that allows to decouple the interface from a concrete implementation and to access the concrete implementation from everywhere in your App" -version: 7.7.0 +version: 8.0.0 maintainer: Thomas Burkhart (@escamoteur) homepage: https://github.com/fluttercommunity/get_it funding: