Skip to content

Commit 98b7d28

Browse files
committed
changeTypeInstanceName added
1 parent f536845 commit 98b7d28

File tree

5 files changed

+141
-2
lines changed

5 files changed

+141
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
## [8.0.0-pre-5] - 25.06.2024 adding `changeTypeInstanceName`
12
## [8.0.0-pre-4] - 03.06.2024 fixing bug in `unregister` that happened if you tried to unregister a named registration by providing an istance instead of the type and the instance name
23
## [8.0.0-pre-3] - 31.05.2024 releaseInstance will now throw if the instance isn't registered
34
## [8.0.0-pre-2] - 29.05.2024 fixing negitiv reference count

lib/get_it.dart

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,24 @@ abstract class GetIt {
422422
/// is registered inside GetIt
423423
bool isRegistered<T extends Object>({Object? instance, String? instanceName});
424424

425+
/// In some cases it can be necessary to change the name of a registered instance
426+
/// This avoids to unregister and reregister the instance which might cause trouble
427+
/// with disposing functions.
428+
/// IMPORTANT: This will only change the the first instance that is found while
429+
/// searching the scopes.
430+
/// If the new name is already in use in the current scope it will throw a
431+
/// StateError
432+
/// [instanceName] the current name of the instance
433+
/// [newInstanceName] the new name of the instance
434+
/// [instance] the instance itself that can be used instead of
435+
/// providing the type and the name. If [instance] is null the type and the name
436+
/// have to be provided
437+
void changeTypeInstanceName<T extends Object>({
438+
String? instanceName,
439+
required String newInstanceName,
440+
T? instance,
441+
});
442+
425443
/// Clears all registered types in the reverse order in which they were registered.
426444
/// Handy when writing unit tests or when disposing services that depend on each other.
427445
/// If you provided dispose function when registering they will be called

lib/get_it_impl.dart

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ class _ServiceFactory<T extends Object, P1, P2> {
6262
final DisposingFunc<T>? disposeFunction;
6363

6464
/// In case of a named registration the instance name is here stored for easy access
65-
final String? instanceName;
65+
String? instanceName;
6666

6767
/// true if one of the async registration functions have been used
6868
final bool isAsync;
@@ -1034,6 +1034,55 @@ class _GetItImplementation implements GetIt {
10341034
}
10351035
}
10361036

1037+
/// In some cases it can be necessary to change the name of a registered instance
1038+
/// This avoids to unregister and reregister the instance which might cause trouble
1039+
/// with disposing functions.
1040+
/// IMPORTANT: This will only change the the first instance that is found while
1041+
/// searching the scopes.
1042+
/// If the new name is already in use in the current scope it will throw a
1043+
/// StateError
1044+
/// [instanceName] the current name of the instance
1045+
/// [newInstanceName] the new name of the instance
1046+
/// [instance] the instance itself that can be used instead of
1047+
/// providing the type and the name. If [instance] is null the type and the name
1048+
/// have to be provided
1049+
@override
1050+
void changeTypeInstanceName<T extends Object>({
1051+
String? instanceName,
1052+
required String newInstanceName,
1053+
T? instance,
1054+
}) {
1055+
assert(instance != null || instanceName != null,
1056+
'You have to provide either an instance or an instanceName');
1057+
1058+
final factoryToRename = instance != null
1059+
? _findFactoryByInstance(instance)
1060+
: _findFactoryByNameAndType<T>(instanceName);
1061+
1062+
if (instance != null) {
1063+
instanceName = factoryToRename.instanceName;
1064+
}
1065+
1066+
throwIfNot(
1067+
factoryToRename.isNamedRegistration,
1068+
StateError(
1069+
'This instance $instance is not registered with a name',
1070+
),
1071+
);
1072+
1073+
final typeRegistration = factoryToRename.registeredIn;
1074+
throwIf(
1075+
typeRegistration.namedFactories.containsKey(newInstanceName),
1076+
StateError(
1077+
'There is already an instance of type ${factoryToRename.registrationType} registered with the name $newInstanceName',
1078+
),
1079+
);
1080+
1081+
typeRegistration.namedFactories[newInstanceName] = factoryToRename;
1082+
typeRegistration.namedFactories.remove(instanceName);
1083+
factoryToRename.instanceName = newInstanceName;
1084+
}
1085+
10371086
/// Clears the instance of a lazy singleton,
10381087
/// being able to call the factory function on the next call
10391088
/// of [get] on that type again.

pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: get_it
22
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"
3-
version: 8.0.0-pre-4
3+
version: 8.0.0-pre-5
44
maintainer: Thomas Burkhart (@escamoteur)
55
homepage: https://github.com/fluttercommunity/get_it
66
funding:

test/get_it_test.dart

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1019,6 +1019,77 @@ void main() {
10191019
throwsA(const TypeMatcher<StateError>()),
10201020
);
10211021
});
1022+
test('change registration name with type and name', () async {
1023+
final getIt = GetIt.instance;
1024+
disposeCounter = 0;
1025+
1026+
getIt.registerSingleton(TestClass(), instanceName: 'instanceName');
1027+
1028+
final TestClass instance1 = getIt.get(instanceName: 'instanceName');
1029+
1030+
expect(instance1 is TestClass, true);
1031+
1032+
getIt.changeTypeInstanceName<TestClass>(
1033+
instanceName: 'instanceName',
1034+
newInstanceName: 'instanceName2',
1035+
);
1036+
1037+
expect(disposeCounter, 0);
1038+
1039+
expect(
1040+
() => getIt<TestClass>(instanceName: 'instanceName'),
1041+
throwsA(const TypeMatcher<StateError>()),
1042+
);
1043+
expect(
1044+
getIt<TestClass>(instanceName: 'instanceName2'),
1045+
const TypeMatcher<TestClass>(),
1046+
);
1047+
});
1048+
1049+
test('change registration name with type and name existing name', () async {
1050+
final getIt = GetIt.instance;
1051+
1052+
getIt.registerSingleton(TestClass(), instanceName: 'instanceName');
1053+
getIt.registerSingleton(TestClass(), instanceName: 'instanceNameExisting');
1054+
1055+
final TestClass instance1 = getIt.get(instanceName: 'instanceName');
1056+
1057+
expect(instance1 is TestClass, true);
1058+
1059+
expect(() {
1060+
getIt.changeTypeInstanceName<TestClass>(
1061+
instanceName: 'instanceName',
1062+
newInstanceName: 'instanceNameExisting',
1063+
);
1064+
}, throwsA(const TypeMatcher<StateError>()));
1065+
});
1066+
1067+
test('change registration name of instance', () async {
1068+
final getIt = GetIt.instance;
1069+
disposeCounter = 0;
1070+
1071+
getIt.registerSingleton(TestClass(), instanceName: 'instanceName');
1072+
1073+
final TestClass instance1 = getIt.get(instanceName: 'instanceName');
1074+
1075+
expect(instance1 is TestClass, true);
1076+
1077+
getIt.changeTypeInstanceName(
1078+
instance: instance1,
1079+
newInstanceName: 'instanceName2',
1080+
);
1081+
1082+
expect(disposeCounter, 0);
1083+
1084+
expect(
1085+
() => getIt<TestClass>(instanceName: 'instanceName'),
1086+
throwsA(const TypeMatcher<StateError>()),
1087+
);
1088+
expect(
1089+
getIt<TestClass>(instanceName: 'instanceName2'),
1090+
const TypeMatcher<TestClass>(),
1091+
);
1092+
});
10221093

10231094
test(
10241095
'can register a singleton with instanceName and retrieve it with generic parameters and instanceName',

0 commit comments

Comments
 (0)