Skip to content

Commit

Permalink
V8 candidate
Browse files Browse the repository at this point in the history
  • Loading branch information
escamoteur committed May 7, 2024
1 parent 86203e7 commit 17cb14b
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 49 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
5 changes: 4 additions & 1 deletion lib/get_it.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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<T> getAll<T extends Object>({
dynamic param1,
dynamic param2,
bool fromAllScopes = false,
});

/// The returned `Future<Iterable>` 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<Iterable<T>> getAllAsync<T extends Object>({
dynamic param1,
dynamic param2,
bool fromAllScopes = false,
});

/// Callable class so that you can write `GetIt.instance<MyType>` instead of
Expand Down
150 changes: 103 additions & 47 deletions lib/get_it_impl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,75 @@ class _Scope {
Future<void> dispose() async {
await disposeFunc?.call();
}

Iterable<T> getAll<T extends Object>({
dynamic param1,
dynamic param2,
}) {
final _TypeRegistration<T>? typeRegistration =
typeRegistrations[T] as _TypeRegistration<T>?;

if (typeRegistration == null) {
return [];
}

final factories = [
...typeRegistration!.factories,
...typeRegistration.namedFactories.values
];
final instances = <T>[];
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<Iterable<T>> getAllAsync<T extends Object>({
dynamic param1,
dynamic param2,
}) async {
final _TypeRegistration<T>? typeRegistration =
typeRegistrations[T] as _TypeRegistration<T>?;

if (typeRegistration == null) {
return [];
}

final factories = [
...typeRegistration!.factories,
...typeRegistration.namedFactories.values
];
final instances = <T>[];
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 {
Expand Down Expand Up @@ -496,45 +565,32 @@ class _GetItImplementation implements GetIt {
Iterable<T> getAll<T extends Object>({
dynamic param1,
dynamic param2,
bool fromAllScopes = false,
}) {
final _TypeRegistration<T>? typeRegistration =
_currentScope.typeRegistrations[T] as _TypeRegistration<T>?;
final Iterable<T> instances;
if (!fromAllScopes) {
instances = _currentScope.getAll<T>(
param1: param1,
param2: param2,
);
} else {
instances = [
for (final scope in _scopes)
...scope.getAll<T>(
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 = <T>[];
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;
}

Expand Down Expand Up @@ -574,32 +630,32 @@ class _GetItImplementation implements GetIt {
Future<Iterable<T>> getAllAsync<T extends Object>({
dynamic param1,
dynamic param2,
bool fromAllScopes = false,
}) async {
final _TypeRegistration<T>? typeRegistration =
_currentScope.typeRegistrations[T] as _TypeRegistration<T>?;
final Iterable<T> instances;
if (!fromAllScopes) {
instances = await _currentScope.getAllAsync<T>(
param1: param1,
param2: param2,
);
} else {
instances = [
for (final scope in _scopes)
...await scope.getAllAsync<T>(
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 = <T>[];
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;
}

Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -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:
Expand Down

0 comments on commit 17cb14b

Please sign in to comment.