#dart
#dart
Вопрос:
Я создал этот класс
class Opacity {
String a,b,c;
Opacity({this.a, this.b,this.c});
}
И я пытаюсь динамически создать экземпляр этого класса, используя только строки и хэш-карту для аргументов.
String type = "Opacity";
List<String> args = {'a': 'a', 'b': 'b','c': 'c'}
И у меня есть одно ограничение, я не могу изменить Opacity
класс.
Для создания экземпляра я думал об использовании отражения для динамического создания класса из строки, но я не могу понять, как динамически передавать аргументы.
Комментарии:
1. Вы могли бы сделать это с помощью отражения, но это доступно только для приложений сервера / командной строки, но не для Web или Flutter. Для таких веб-приложений и приложений Flutter, вероятно, лучше создать фабричный конструктор / метод, который знает, как обращаться с такими строками, а также создавать экземпляры и передавать параметры для предопределенного набора классов.
Ответ №1:
Для динамической передачи аргументов конструктору вы можете использовать newInstance
метод ClassMirror
.
Например
MirrorSystem mirrors = currentMirrorSystem();
ClassMirror classMirror = mirrors.findLibrary(Symbol.empty).declarations[new Symbol('Opacity')];
print(classMirror);
var arguments = {'a': 'a', 'b': 'b', 'c': 'c'}.map((key, value) {
return MapEntry(Symbol(key), value);
});
var op = classMirror.newInstance(Symbol.empty, [], arguments);
Opacity opacity = op.reflectee;
print("opacity.a: ${opacity.a}");
print("opacity.b: ${opacity.b}");
print("opacity.c: ${opacity.c}");
Ответ №2:
Переход от строки к имени источника и далее к объекту, обозначаемому этим именем источника, является отражением. Это доступно только через dart:mirrors
библиотеку или, если вы генерируете код заранее, возможно, используя package:reflectable
.
В этом Dart отличается от такого языка, как JavaScript, где вы можете проверять все значения во время выполнения.
Без отражения вы можете вызвать конструктор только в том случае, если у вас есть реальный код, выполняющий этот вызов в вашем коде. Это означало бы, что у вас должен быть код, подобный Opacity(a: ..., b: ..., c: ...)
, по крайней мере, в одном месте вашего кода. Вы могли бы определить функцию, подобную:
Opacity createOpacity(Map<String, String> args) =>
Opacity(a: args["a"], b: args["b"], c: args["c"]);
Тогда, возможно, вы могли бы зарегистрировать его по имени как:
Map<String, Function> factories = {"Opacity": createOpacity};
и, наконец, использовать его как:
var type = "Opacity";
var args = {'a': 'a', 'b': 'b', 'c': 'c'};
Opacity myOpacity = factories[type](args);