Thanks, but I think it is impossible to achieve what I want anyway =(
See, I’m using a library where I need to map one class to another (a Query class to a Query Handler class, a Command class to a Command Handler class, etc.). It’s very tedious to do it by hand:
final queryHandlers = <Type, IQueryHandler<IQuery<dynamic>, dynamic> Function()>{
AppVersionQuery: AppVersionQueryHandler.new,
DeviceInfoQuery:
() => const DeviceInfoQueryHandler(deviceInfoService: deviceInfoService),
UserSettingValueQuery:
() => UserSettingValueQueryHandler(
authenticationService: authenticationService,
databaseService: databaseService,
),
CurrentThemeQuery:
() => CurrentThemeQueryHandler(
authenticationService: authenticationService,
databaseService: databaseService,
defaultUserTheme: defaultThemeSetting,
),
UserCredentialsQuery:
() => UserCredentialsQueryHandler(
authenticationService: authenticationService,
),
CurrentUserRefQuery:
() =>
CurrentUserRefQueryHandler(authenticationService: authenticationService),
};
Then, I wondered: what If I use the injectable | Dart package to automagically register all my classes without me having to do this manual setup (which is the same for pure GetIt as well, that’s why Injector exists in the first place).
So, with all classes registered, I could somehow list and search of all registrations that starts with IQueryHandler<
and, somehow, create that setup above.
But Dart makes that impossible:
-
There is no way to create a type from a String (like C# Type.GetType("SomeCommand")
).
-
There is no guarantee whatsoever that "${SomeCommand}" == "SomeCommand"
, because Dart compiler may obfuscate/compact type names (which is not a problem, since all strings will match, they would just not have the same value (i.e.: instead of SomeCommand
, could be $_obf234
, but it points to the same type)).
So, in the end, I did write a modified version of GetIt to get the list of registered types, but I was unable to actually construct any types from it.
The library I use convert types to strings and keep a map of type name
: handler factory
:
Future<List<TResult>> _dispatch(
TAction action, [
bool ignoreHandlers = false,
]) async {
final typeName = action.runtimeType.toString();
final handlerFactories = _handlerFactories[typeName];
So, when calling this as _dispatch(const AppVersionQuery())
, AppVersionQueryHandler
is constructed and the .handler(AppVersionQuery query)
is executed.