In dart is it possible to instantiate a class from a string?

1,934 views
Skip to first unread message

mario gonzalez

unread,
Jan 9, 2013, 12:18:43 PM1/9/13
to mi...@dartlang.org
In dart is it possible to instantiate a class from a string?

For example:
vanilla in javascript:  
var myObject = window[classNameString];



Objective-C:  
id myclass = [[NSClassFromString(@"MyClass") alloc] init];



James Wendel

unread,
Jan 9, 2013, 12:46:06 PM1/9/13
to mi...@dartlang.org
Using Mirrors you should be able to.  I believe a lot of the Mirror system is still being worked on, but it should be do-able (assuming all the pieces of mirrors is implemented).


From the MirrorSystem, you could get a map of the Libraries, and from that you can a map of the Classes.  From the ClassMirror, you can use the newInstance method to create a instance of the class.

Shailen Tuli

unread,
Jan 9, 2013, 12:49:16 PM1/9/13
to mi...@dartlang.org
This question is also asked on StackOverflow. If you have an answer, please add it there. HEre's the link:

Ladislav Thon

unread,
Jan 9, 2013, 2:42:59 PM1/9/13
to mi...@dartlang.org
Using Mirrors you should be able to.  I believe a lot of the Mirror system is still being worked on, but it should be do-able (assuming all the pieces of mirrors is implemented).


From the MirrorSystem, you could get a map of the Libraries, and from that you can a map of the Classes.  From the ClassMirror, you can use the newInstance method to create a instance of the class.

Everything necessary for this is in place. Full example looks like this:

import 'dart:mirrors';

class Foo {
  final foo;
  Foo(this.foo);
  String toString() => 'foo $foo';
}

main() {
  var mirrors = currentMirrorSystem();
  var lib = mirrors.libraries['file:///home/ladicek/work/dart/projects/playground/mirrors.dart'];
  var fooClass = lib.classes['Foo'];
  fooClass.newInstance('', ['bar']).then((fooInstance) {
    print('foo = ${fooInstance.reflectee}');
  });
}

But, eh, the library URI in the code... there used to be a MirrorSystem.rootLibrary getter, but that seems to be gone. Can anyone comment on that?

Also, if I print a map of libraries (print mirrors.libraries), I get

{dart:collection: LibraryMirror on 'dart:collection', dart:io: LibraryMirror on 'dart:io', dart:isolate: LibraryMirror on 'dart:isolate', dart:mirrors: LibraryMirror on 'dart:mirrors', dart:async: LibraryMirror on 'dart:async', dart.json: LibraryMirror on 'dart.json', dart:nativewrappers: LibraryMirror on 'dart:nativewrappers', crypto: LibraryMirror on 'crypto', dart:math: LibraryMirror on 'dart:math', dart:core: LibraryMirror on 'dart:core', builtin: LibraryMirror on 'builtin', utf: LibraryMirror on 'utf', dart:scalarlist: LibraryMirror on 'dart:scalarlist', dart.uri: LibraryMirror on 'dart.uri', file:///home/ladicek/work/dart/projects/playground/mirrors-new.dart: LibraryMirror on 'file:///home/ladicek/work/dart/projects/playground/mirrors-new.dart'}

The keys are pretty inconsistent. The dart:core library is keyed by dart:core, dart:json by dart.json, dart:utf by utf... That is more than work in progress :-) I'm SO not going to post this on StackOverflow.

LT

James Wendel

unread,
Jan 9, 2013, 2:45:55 PM1/9/13
to mi...@dartlang.org
As long as the code you are trying to call is part of a declared library, it is much cleaner to include it.  I posted a solution on StackOverflow to that effect.

Ladislav Thon

unread,
Jan 9, 2013, 2:49:42 PM1/9/13
to mi...@dartlang.org
As long as the code you are trying to call is part of a declared library, it is much cleaner to include it.  I posted a solution on StackOverflow to that effect.

Doh! I didn't think about that, but it's pretty obvious now :-)

Also, note that named arguments are not yet implemented. Positional are, though.

LT

SwarmShepherd

unread,
Jan 9, 2013, 11:54:09 PM1/9/13
to mi...@dartlang.org

Hey guys,

I did things differently in Ruby than I'm doing them in Dart.   I ended up coming up with a simple class that I can accumulate 1 or more classes into (all the classes in a library, whatever) and then any method that is qualified/accumulated (the class name breaks ties) can be called by class & name as a string by the "invoker" method.   No big whoop!  But instead of having this code show up in multiple places with the rather fragile looking string handling and all, this way its all shoved into one small class that can be used instantiated and used multiple places...  I'm pretty happy with that. 

I'll include my code below, but forgive me as at this stage of my project I am still using a bunch of "Helper Functions on Lists & Maps that'll have to be replaced but they are for simple functions:

class ClassMethodMapper {
 
Map    _helperMirrorsMap, _methodMap;

 
void accum_class_map(Object myClass){
   
InstanceMirror helperMirror = reflect(myClass);
   
List methodsAr  = helperMirror.type.methods.values;
   
String classNm  = myClass.toString().split("'")[1]; ///#FRAGILE?  
    MAP_add
(_helperMirrorsMap, classNm, helperMirror);
    methodsAr
.forEach(( method) {
     
String key = method.simpleName;
     
if (key.charCodeAt(0) != 95) { //To ignore private methods
        MAP_add
(_methodMap, "${classNm}.${key}()", method);
     
}
   
});
 
}

 
Map invoker( String methodNm ) {
   
var method = MAP_fetch(_methodMap, methodNm, null);
   
if (method != null) {    
     
String classNm = methodNm.split('.')[0];    
     
InstanceMirror helperMirror = MAP_fetch(_helperMirrorsMap, classNm);
      helperMirror
.invoke(method.simpleName, []);
   
}
 
}


 
ClassMethodMapper() {
    _methodMap        
= {};
    _helperMirrorsMap  
= {};
 
}
}//END_OF_CLASS( ClassMethodMapper );  


Its a really simple idea that I thought of from a posting from Yosaf, thanks!

I still Dart with a bit of a Ruby accent?  Sorry about that...

_swarmii

Ladislav Thon

unread,
Jan 10, 2013, 4:41:03 AM1/10/13
to mi...@dartlang.org
But, eh, the library URI in the code... there used to be a MirrorSystem.rootLibrary getter, but that seems to be gone. Can anyone comment on that?

I just noticed that it still exists, but it was moved to IsolateMirror. Which makes sense, actually. The code looks like this:

var lib = currentMirrorSystem().isolate.rootLibrary;
...

LT
Reply all
Reply to author
Forward
0 new messages