Dart - NoSuchMethodError: Class 'Module' has no instance getter 'String' - dart

Could some please explain what is wrong?
I try to get an item by key from HashMap:
If I do it that way:
var stringProvider = providersHolder[String]
I get an error:
NoSuchMethodError: Class 'Module' has no instance getter 'String'.
If I do it next way:
var stringProvider = providersHolder[providersHolder.keys.last]
where providersHolder.keys.last == String
I get success.
Here is a full listing:
class Module {
HashMap providersHolder = new HashMap<Type, ItemCreator>();
void addProvider<T, M extends Module>(ItemCreator<T, M> itemCreator) {
providersHolder[T] = itemCreator;
}
}
class Test {
Test() {
var module = Module();
module.addProvider((module) => new Ticker());
module.addProvider((module) => "hello");
var ticketProvider = module.providersHolder[Ticker]; //success
var stringProvider = module.providersHolder[String]; //error
}
}
Here is a watcher:

Could you provide more details on how ItemCreator was defined? This will help us replicate the behavior you've encountered. If you're still having the same errors, you can also run flutter doctor -v to check for any errors or warnings.

Related

How do I get an actual object dynamically in Dart? [duplicate]

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];
You need to know the library name and class name to make things work properly. Assume you know both, the below example will instantiate the TestClass and call doStuff on it.
library test;
import "dart:mirrors";
class TestClass {
doStuff() => print("doStuff was called!");
}
main() {
MirrorSystem mirrors = currentMirrorSystem();
LibraryMirror lm = mirrors.libraries['test'];
ClassMirror cm = lm.classes['TestClass'];
Future tcFuture = cm.newInstance('', []);
tcFuture.then((InstanceMirror im) {
var tc = im.reflectee;
tc.doStuff();
});
}
A few notes about this solution:
The library test we are trying to load the class from is already imported in the VM, which makes this case a bit easier.
the call the newInstance allows for passing parameters to the constructor. Positional arguments are implemented, but named parameters are not yet implemented (as of the M2 release).
newInstance returns a Future to allow it to work across isolates.
The syntax has changed.
I got it working this way
library test;
import "dart:mirrors";
class TestClass {
doStuff() => print("doStuff was called!");
}
main() {
MirrorSystem mirrors = currentMirrorSystem();
LibraryMirror lm = mirrors.libraries.values.firstWhere(
(LibraryMirror lm) => lm.qualifiedName == new Symbol('test'));
ClassMirror cm = lm.declarations[new Symbol('TestClass')];
InstanceMirror im = cm.newInstance(new Symbol(''), []);
var tc = im.reflectee;
tc.doStuff();
}
If there are more libraries named 'test' this will fail though.
Try:
Map models = {"Player": Player.instatiate};
var player = models["Player"]();
class Player{
static instatiate() => Player();
}
This was an issue that has plagued me until I figured that I could implement a crude from method to handle the conversion of encoded Json Objects/strings or Dart Maps to the desired class.
Below is a simple example that also handles nulls and accepts JSON (as the string parameter)
import 'dart:convert';
class PaymentDetail
{
String AccountNumber;
double Amount;
int ChargeTypeID;
String CustomerNames;
PaymentDetail({
this.AccountNumber,
this.Amount,
this.ChargeTypeID,
this.CustomerNames
});
PaymentDetail from ({ string : String, object : Map }) {
var map = (object==null) ? (string==null) ? Map() : json.decode(string) : (object==null) ? Map() : object;
return new PaymentDetail(
AccountNumber : map["AccountNumber"] as String,
Amount : map["Amount"] as double,
ChargeTypeID : map["ChargeTypeID"] as int,
CustomerNames : map["CustomerNames"] as String
);
}
}
Below is it's implementation
PaymentDetail payDetail = new PaymentDetail().from(object: new Map());
PaymentDetail otherPayDetail = new PaymentDetail().from(object: {"AccountNumber": "1234", "Amount": 567.2980908});
Once again, this is simplistic and tedious to clone throughout the project but it works for simple cases.

Get private variable by reflection in dart

I would like to get private variable in an object in dart.
This variable has no getter so I want to do this with reflection.
I try many way but nothing works to me.
For exemple, when I do this:
var reflection = reflect(this);
InstanceMirror field = reflection.getField(new Symbol(fieldName));
I get an error:
No getter for fieldName.
It's normal because the variable hasn't getter.
How can I get this variable ?
EDIT with a test code:
Here is my reflect test (test variable is a reflectClass(MyClass))
reflectClass(Injector).declarations.keys.forEach((e) => test.getField(e, test.type.owner))
I get this error:
Class '_LocalInstanceMirror' has no instance method 'getField' with
matching arguments.
If I do this:
reflectClass(Injector).declarations.keys.forEach((e) => test.getField(e))
I get:
Class 'DynamicInjector' has no instance getter
'_PRIMITIVE_TYPES#0x1b5a3f8d'.
Same thing with values of declarations.
The error message you got is actually correct. The class has a getter for this field.
Dart implicitly creates getters for all and setters for all non-final/non-const fields.
It seems access to private members isn't yet supported in Dart2JS.
see https://code.google.com/p/dart/issues/detail?id=13881
Here an example how to access private fields:
(example from https://code.google.com/p/dart/issues/detail?id=16773)
import 'dart:mirrors';
class ClassWithPrivateField {
String _privateField;
}
void main() {
ClassMirror classM = reflectClass(ClassWithPrivateField);
Symbol privateFieldSymbol;
Symbol constructorSymbol;
for (DeclarationMirror declaration in classM.declarations.values) {
if (declaration is VariableMirror) {
privateFieldSymbol = declaration.simpleName;
} else if (declaration is MethodMirror && declaration.isConstructor) {
constructorSymbol = declaration.constructorName;
}
}
// it is not necessary to create the instance using reflection to be able to
// access its members with reflection
InstanceMirror instance = classM.newInstance(constructorSymbol, []);
// var s = new Symbol('_privateField'); // doesn't work for private fields
// to create a symbol for a private field you need the library
// if the class is in the main library
// var s = MirrorSystem.getSymbol('_privateField', currentMirrorSystem().isolate.rootLibrary);
// or simpler
// var s = MirrorSystem.getSymbol('_privateField', instance.type.owner);
for (var i=0; i<1000; ++i) {
instance.setField(privateFieldSymbol, 'test');
print('Iteration ${instance.getField(privateFieldSymbol)}');
}
}
using dson or serializable you can do it in next way:
library example_lib;
import 'package:dson/dson.dart';
// this should be the name of your file
part 'example.g.dart';
#serializable
class Example extends _$ExampleSerializable {
var _privateVar;
}
main() {
var example = new Example();
example['_privateVar'] = 'some value';
print('example._privateVar: ${example._privateVar}');
print('example["_privateVar"]: ${example["_privateVar']}");
}

how can i to instance an object by the classname in dart [duplicate]

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];
You need to know the library name and class name to make things work properly. Assume you know both, the below example will instantiate the TestClass and call doStuff on it.
library test;
import "dart:mirrors";
class TestClass {
doStuff() => print("doStuff was called!");
}
main() {
MirrorSystem mirrors = currentMirrorSystem();
LibraryMirror lm = mirrors.libraries['test'];
ClassMirror cm = lm.classes['TestClass'];
Future tcFuture = cm.newInstance('', []);
tcFuture.then((InstanceMirror im) {
var tc = im.reflectee;
tc.doStuff();
});
}
A few notes about this solution:
The library test we are trying to load the class from is already imported in the VM, which makes this case a bit easier.
the call the newInstance allows for passing parameters to the constructor. Positional arguments are implemented, but named parameters are not yet implemented (as of the M2 release).
newInstance returns a Future to allow it to work across isolates.
The syntax has changed.
I got it working this way
library test;
import "dart:mirrors";
class TestClass {
doStuff() => print("doStuff was called!");
}
main() {
MirrorSystem mirrors = currentMirrorSystem();
LibraryMirror lm = mirrors.libraries.values.firstWhere(
(LibraryMirror lm) => lm.qualifiedName == new Symbol('test'));
ClassMirror cm = lm.declarations[new Symbol('TestClass')];
InstanceMirror im = cm.newInstance(new Symbol(''), []);
var tc = im.reflectee;
tc.doStuff();
}
If there are more libraries named 'test' this will fail though.
Try:
Map models = {"Player": Player.instatiate};
var player = models["Player"]();
class Player{
static instatiate() => Player();
}
This was an issue that has plagued me until I figured that I could implement a crude from method to handle the conversion of encoded Json Objects/strings or Dart Maps to the desired class.
Below is a simple example that also handles nulls and accepts JSON (as the string parameter)
import 'dart:convert';
class PaymentDetail
{
String AccountNumber;
double Amount;
int ChargeTypeID;
String CustomerNames;
PaymentDetail({
this.AccountNumber,
this.Amount,
this.ChargeTypeID,
this.CustomerNames
});
PaymentDetail from ({ string : String, object : Map }) {
var map = (object==null) ? (string==null) ? Map() : json.decode(string) : (object==null) ? Map() : object;
return new PaymentDetail(
AccountNumber : map["AccountNumber"] as String,
Amount : map["Amount"] as double,
ChargeTypeID : map["ChargeTypeID"] as int,
CustomerNames : map["CustomerNames"] as String
);
}
}
Below is it's implementation
PaymentDetail payDetail = new PaymentDetail().from(object: new Map());
PaymentDetail otherPayDetail = new PaymentDetail().from(object: {"AccountNumber": "1234", "Amount": 567.2980908});
Once again, this is simplistic and tedious to clone throughout the project but it works for simple cases.

Why can't this simple Dart code be compiled?

Here is some simple Dart code:
class P {
var name = myname();
String myname() => "PPP";
}
main() {
new P();
}
It reports this error when running:
Error: line 2 pos 14: illegal implicit access to receiver 'this'
var name = myname();
^
What is causing this error?
You're attempting to evaluate a non-static method in a static context (see note). You can either mark the method as static:
class P {
var name = myname();
static String myname() => "PPP";
}
Or evaluate the code in a non-static context:
class P {
var name;
P() {name = myname();}
static String myname() => "PPP";
}
Note: The concept of "static context" here is my mental model, which may or may not perfectly match how Dart works. It may be more correct to note that this simply isn't available in a field initializer, explicitly or implicitly.

How can I use Reflection (Mirrors) to access the method names in a Dart Class?

I need to "fetch" the methods in a Dart Class.
How can I do this?
And I want to be able to call the methods.
May I see an example?
Here's an easy copy-pasteable code sample:
import 'dart:mirrors';
import 'dart:io';
main() {
var im = reflect(new File('test')); // Retrieve the InstanceMirror of some class instance.
im.type.methods.values.forEach((MethodMirror method) => print(method.simpleName));
}
Output is:
existsSync
_delete
exists
directory
_getDecodedLines
readAsTextSync
readAsBytesSync
readAsLinesSync
_directory
throwIfError
lastModifiedSync
readAsLines
open
_ensureFileService
deleteSync
delete
_exists
length
openInputStream
create
_create
readAsText
_openStdioSync
openOutputStream
_fullPath
_lastModified
fullPathSync
readAsBytes
lastModified
_openStdio
_open
openSync
lengthSync
directorySync
fullPath
createSync
_lengthFromName
Here is a basic example:
(Note: You will want to have a (very) up to date version of the SDK for this, this was done in Dart Editor version 0.2.1_r14167, Dart SDK version 0.2.1.2_r14167 Nov 2, 2012)
My most sincere Thanks to Gilad of the Google Dart Team for providing this example!
#import('dart:mirrors');
class MyClass {
String _test;
String get test => _test;
set test(String paramVal) => _test = paramVal;
void my_method() {
}
void print_test(){
print("test string is: ${_test}");
}
MyClass(String test) {
_test = test;
}
}
main() {
MyClass myClass = new MyClass("Make my day, PUNK.");
myClass.print_test();
//ClassMirror myClassMirror = reflect(myClass).type;
InstanceMirror myClassInstanceMirror = reflect(myClass);
ClassMirror MyClassMirror = myClassInstanceMirror.type;
Map<String, MethodMirror> map = MyClassMirror.methods;
print("map = ${map}");
map.values.forEach( (MethodMirror mm){
myClassInstanceMirror.invoke(mm.simpleName,[]);
});
}
Concerning Reflection I have just written a couple of "Helper Functions" for fetching a LIST of the method names (not a Map) and invoking the method... all I can say for sure is that it works right now. There are likely technical reasons for not doing it this way - but in my case this does not run in a complex environment. However, I do think they nicely mask over a lot of details that not everybody is going to want to deal with.
Here's a functioning demonstration with and without the Helper functions:
#import('dart:mirrors');
class MyClass {
String _test;
String get test => _test;
set test(String paramVal) => _test = paramVal;
void my_method1(){print("in method1");}
void my_method2(){print("in method2");}
void print_test(){
print("test string is: ${_test}");
}
MyClass(String test) {
_test = test;
}
}
//Helper Methods
InstanceMirror hMr;
List REFLECT_methods(Object myClass) {hMr=reflect(myClass);return(hMr.type.methods.values);}
REFLECT_invoke(MethodMirror mm){hMr.invoke(mm.simpleName, []);}
main() {
MyClass myClass = new MyClass("Make my day, PUNK.");
print("\n=======Using Raw Reflection================");
InstanceMirror myClassInstanceMirror = reflect(myClass);
ClassMirror MyClassMirror = myClassInstanceMirror.type;
Map<String, MethodMirror> map1 = MyClassMirror.methods;
map1.values.forEach( (MethodMirror mm){
myClassInstanceMirror.invoke(mm.simpleName,[]);
});
print("\n==========Using Helper functions=============");
List list2 = REFLECT_methods(myClass);
list2.forEach((method){
REFLECT_invoke(method);
});
}

Resources