-
Notifications
You must be signed in to change notification settings - Fork 28.5k
Improved support for runtimeType and <T> type params #60603
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I think there is the var factory = extractIterableTypeArgument(responseType, <T>() => _typeFactory[T]) as IConvertible; |
Hi @xvrh |
I believe something like dart-lang/language#356 is what is needed here, but I could be wrong. You want the ability to create a List of any type that has a |
I have re-posted this on the dart language project dart-lang/language#1056 |
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of |
I would like to be able to use
runtimeType
and/or be able to interrogate the type of a type param at runtime, to improve deserialization of Lists in a generic way.Use case
I have a json list, containing
SearchResult
items. I have a type param representing the desired object List. I also have an emptyList<SearchResult>
object that I could deserialize into:The issue I am having is I can't find a reliable way to obtain "SearchResult" inside this function. (I then look up "SearchResult" in a type factory dictionary, to obtain a function that deserializes each json list element to concrete SearchResult instances).
Unreliable option 1:
responseType.runtimeType.toString().replaceFirst("List<","").replaceFirst(">","");
This worked fine in debug mode, giving "SearchResult", but when I went to release mode some time later, it failed. This was because
List<SearchResult>().runtimeType.toString()
gives "_GrowableList" in release mode.This specific behaviour isn't documented anywhere, there's only a warning not to use
runtimeType
for anything in Chapter 2, section 2.13 of "The Dart Programming Language" by Gilad Bracha:and then a bit after that:
So basically I gather you can't and really shouldnt rely on
runtimeType
.Unreliable option 2:
T.toString().replaceFirst("List<","").replaceFirst(">","");
This works, because T.toString() gives "List", on both dev and release builds (no _GrowableList appears). But this is pretty unreliable too, as it's just a
.toString()
which is undocumented. There are no other methods available on T to call (T.runtimeType.toString()
gives "_Type").Proposal
Either:
dart:mirrors
support in Flutter, eg a cut-down version ofClassMirror
would probably suffice, orType
to return the name of the type, or<T>
type tokens, either by makingT.toString()
a documented API, or providing an alternative API that returns the name of the type represented by the token. It's great that there's no type erasure (unlike Java), but its usefulness is still limited. You can't test if T is a list:Extra background
I'm trying to fix an issue with the ServiceStack dart client, which has issues deserializing List API responses. ServiceStack codegen gives us a nicer way to generate strongly-typed APIs in .NET, and call them from many many client languages.
Request classes implement
IReturn<T>
whereT
is the return type.Usage: Given a ServiceStack
client
with a genericsend
function:Future<T> send<T>(IReturn<T> request)
,and a request of class:
class SearchRequest implements IReturn<List<SearchResult>>
Then in dart we can write:
var result = await client.send(SearchRequest(searchTerm: query));
and result is inferred to be of type
List<SearchResult>
It makes API calls extremely easy.
The
IReturn
request objects implement a functionT createResponse()
, which creates a new, empty response object, on whichfromMap(Map<String, dynamic> json)
is then called to inflate it with the json response. This works fine for Object responses, but not for Lists.Complete example
we then look up the type, "SearchResult", inside a type factory dictionary, which looks something like:
_typeFactory = <String, IConvertible Function()>{'SearchResult': () => new SearchResult(),...}
So then the deserializer can call:
The text was updated successfully, but these errors were encountered: