Получение значений получателя с помощью dart: mirrors Reflection

У меня есть следующий код (упрощенный), который использует отражение для итерации полей и геттеров класса и вывода значений. Класс ContainsGetter содержит геттер, а класс ContainsField содержит простое поле.

Используя библиотеку dart:mirrors, я могу получить значение поля с помощью instanceMirror.getField(fieldName)), но не получатель с помощью instanceMirror.invoke(fieldName,[]).

Следующий сценарий Dart (использующий сборку 17463) дает следующий результат:

сценарий приложения

import 'dart:mirrors';

class ContainsGetter { // raises an error
  String get aGetter => "I am a getter";
}

class ContainsField { // works fine
  String aField = "I am a field";
}

void main() {
  printFieldValues(reflect(new ContainsField()));
  printGetterValues(reflect(new ContainsGetter()));
}

void printFieldValues(instanceMirror) {
  var classMirror = instanceMirror.type;
  classMirror.variables.keys.forEach((key) {
    var futureField = instanceMirror.getField(key); // <-- works ok
    futureField.then((imField) => print("Field: $key=${imField.reflectee}"));
  });
}

void printGetterValues(instanceMirror) {
  var classMirror = instanceMirror.type;
  classMirror.getters.keys.forEach((key) {
    var futureValue = instanceMirror.invoke(key,[]); // <-- fails
    futureValue.then((imValue) => print("Field: $key=${imValue.reflectee}"));
  });
}

вывод

Field: aField=I am a field
Uncaught Error: Compile-time error during mirrored execution: <Dart_Invoke: did not find instance method 'ContainsGetter.aGetter'.>
Stack Trace:
#0      _LocalObjectMirrorImpl._invoke (dart:mirrors-patch:163:3)
#1      _LocalObjectMirrorImpl.invoke (dart:mirrors-patch:125:33)

(Допустимо, что «этот бит еще не написан!»)


person Chris Buckett    schedule 24.01.2013    source источник


Ответы (1)


Ааа, я только что разобрался. Хотя aGetter похож на метод в своей реализации, вы используете getField(), а не invoke, чтобы получить его значение.

void printGetterValues(instanceMirror) {
  var classMirror = instanceMirror.type;
  classMirror.getters.keys.forEach((key) {
    var futureValue = instanceMirror.getField(key); // <-- now works ok
    futureValue.then((imValue) => print("Field: $key=${imValue.reflectee}"));
  });
}
person Chris Buckett    schedule 24.01.2013
comment
На самом деле, это больше похоже на то, что определения полей всегда генерируют геттеры и сеттеры, по крайней мере, на уровне семантики языка (не уверен в реализациях), поэтому getField / setField всегда вызывает геттеры / сеттеры :-) - person Ladicek; 25.01.2013
comment
@Ladicek - круто спасибо. Мне кажется, что функция mirror getField() вводит в заблуждение - конечно, я всегда должен иметь возможность invoke(getter) или invoke(field) и получить значение обратно (или invoke(field, [value]) и вызвать установщик). Почему существует различие между getField и invoke, если за кулисами они фактически делают то же самое? - person Chris Buckett; 26.01.2013
comment
Без понятия. Но это как бы отражает синтаксис - вызов методов и доступ к полям (= вызов геттеров / сеттеров) тоже выглядит иначе. - person Ladicek; 28.01.2013