Создать экземпляр класса из строки в дартланге

#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);