2
votes

I'm trying to call a method of an object in dart, that is mirrored using dart:mirrors. The object I'd like to use is a instance of a class, that is defined in a library of another file.

main.dart

import 'dart:mirrors';

main(List<String> args) {
  var libName = args[0];
  var className = args[1];
  var methodName = args[2];
  MirrorSystem mirrors = currentMirrorSystem();
  LibraryMirror lm = mirrors.findLibrary(new Symbol(libName));
  ClassMirror cm = lm.declarations[new Symbol(className)];
  InstanceMirror im = cm.newInstance(new Symbol(''), []);
  im.invoke(new Symbol(methodName), []);
}

I wrote another file for testing:

test.dart

library test;

class TestClass {
  doStuff() => print("doStuff was called!");
}

If I run main.dart I get an exception:

dart main.dart test TestClass doStuff
Unhandled exception:
Exception: There is no library named 'test'
...

I can add an import statement of the library in main.dart and everything is fine

import 'test.dart';

but I know the name of the library only at runtime.

How can I import the library at runtime or is there a different approach?

1
You currently can't dynamically add code to a running Dart application. This feature might be added eventually. What you can do is import all possible libraries. - Günter Zöchbauer
@GünterZöchbauer DeferredLibrary won't help? - JAre
Unfortunately no, this is when you build to JavaScript you get one monolithic JavaScript file which will be loaded entirely before the code can be executed. Using deferred loading you can split libraries from the main package and to be loaded on demand. But you still have to import the library. deferred loading also works in other scenarios (plain Dart) but I thought using this scenario would demonstrate the point more clearly. - Günter Zöchbauer
The only feature that might help are isolates. You can start isolates from Dart or JavaScript files not known at compile time of the main isolates code. But isolates run in their own space and currently only allow passing serialized data between them. There is for example no way to access the DOM from an isolate that is not the main isolate. - Günter Zöchbauer
I forgot to say, that I'm writing a command-line app. How would you import all possible libraries? - maiermic

1 Answers

2
votes

Till there is a better solution, I use a simple workaround. I call another program, that adds all necessary imports to my main file and executes it:

import 'dart:io';

main(List<String> args) {
  var template = new File('main.dart');
  var tmp = new File('tmp.dart');

  template.readAsString().then((String contents) {
    // add necessary imports to template
    var imp = args[0];
    var code = "import '$imp.dart';\n" + contents;
    tmp.writeAsStringSync(code);
    // run modified template
    var cmdArgs = [tmp.absolute.path];
    cmdArgs.addAll(args);
    Process.run('dart', cmdArgs).then((ProcessResult results) {
      print(results.stdout);
    });
  });
}

Since I'm writing a command-line app, this isn't too bad.