2

I have created this class

class Opacity {
  String a,b,c;

  Opacity({this.a, this.b,this.c});
}

And I'm trying to dynamically create an instance of this class only using strings and an hashmap for arguments.

String type = "Opacity";
List<String> args = {'a': 'a', 'b': 'b','c': 'c'}

And I have one constraint, I can't modify the Opacity class.

For creating the instance I thought about using reflection to dynamically create the class from string but I can't figure out how to pass the arguments dynamically.

1
  • 1
    You could do that using reflection, but that's only available for server/command-line apps, but not for Web, or Flutter. For such Web and Flutter apps it's probably better to create a factory constructor/method that knows how to deal with such strings and to create instances and pass parameters for a predefined set of classes. Commented Mar 14, 2019 at 20:30

2 Answers 2

4

For passing arguments dynamically to the constructor you can use newInstance method of ClassMirror.

For example

  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}");
Sign up to request clarification or add additional context in comments.

Comments

1

Going from a string to a source name, and further to the thing denoted by that source name, is reflection. It's only available through the dart:mirrors library, or if you generate code ahead-of-time, perhaps using package:reflectable.

This is a point where Dart differs from a language like JavaScript, where you can inspect all values at run-time.

Without reflection, the only way you can call a constructor is if you have actual code performing that call in your code. That would mean that you have to have code like Opacity(a: ..., b: ..., c: ...) at least in one place in your code. You could define a function like:

Opacity createOpacity(Map<String, String> args) => 
    Opacity(a: args["a"], b: args["b"], c: args["c"]);

Then you could perhaps register it by name as:

Map<String, Function> factories = {"Opacity": createOpacity};

and finally use it as:

var type = "Opacity";
var args = {'a': 'a', 'b': 'b', 'c': 'c'};
Opacity myOpacity = factories[type](args);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.