google / reflectable.dart

Reflectable is a Dart library that allows programmers to eliminate certain usages of dynamic reflection by specialization of reflective code to an equivalent implementation using only static techniques. The use of dynamic reflection is constrained in order to ensure that the specialized code can be generated and will have a reasonable size.

Home Page:https://pub.dev/packages/reflectable

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Provide access to a type from a `TypeMirror`

eernstg opened this issue · comments

A TypeMirror has a member hasReflectedType and a member reflectedType, and the latter returns a Type for the type which is mirrored by this TypeMirror.

Here is an example of the kind of data provided by reflectedType:

      <Type>[
        prefix0.A,
        const r.FakeType(r'test_reflectable.test.class_property_test._B'),
        prefix0.D,
        prefix0.C
      ]

In many cases, these Type objects are obtained by evaluating a typename denoting a class or type alias (for instance, the library imported with prefix prefix0 above contains class A, class C, class D).

We could actually create a construct that would enable the use of such types as types:

    <void Function(void Function<X>())>[
      (f) => f<prefix0.A>(),
      (f) => throw "Cannot `callWithReflectedType` when type is private",
      (f) => f<prefix0.D>(),
      (f) => f<prefix0.C>(),
    ];

The TypeMirror class would have a new member callWithReflectedType:

abstract class TypeMirror implements DeclarationMirror {
  ...
  void callWithReflectedType(void Function<X>() f) =>
    reflector.typeCallers[reflectedTypeIndex](f);
  ...
}

We would then be able to use it as follows:

@reflector
class C {}

void main() {
  TypeMirror typeMirror = reflector.reflectType(C);
  late Map map;
  if (typeMirror.hasReflectedType) { // This will be true, so we ignore the `else` case.
    typeMirror.callWithReflectedType(<X>() => map = <String, X>{});
  }
}

The callback which is passed to callWithReflectedType will receive the actual type mirrored by the TypeMirror as a normal Dart type argument, which means that we can use that type under the name X (or whatever we choose to call the type variable of the callback). For instance, we can create a Map<String, C> when the type mirror is a mirror of C.