dart reflection call by String - dart

I want to wrote method which call all function in class:
class Example extends MyAbstractClass {
void f1(){...}
void f2(){...}
void f3(){...}
Example(){
callAll();//this call f1(), f2() and f3().
}
}
I have problem in this part of code:
reflectClass(this.runtimeType).declarations.forEach((Symbol s, DeclarationMirror d) {
if (d.toString().startsWith("MethodMirror on ")) {
String methodName = d.toString().substring(16).replaceAll("'", "");
print(methodName);
// How to call function by name methodName?
}
});

instead of
if (d.toString().startsWith("MethodMirror on ")) {
you can use
if (d is MethodMirror) {
You need an InstanceMirror of an instance of the class. I think in your case this would be
var im = reflect(this).invoke(d.simpleName, []);
im.declarations.forEach((d) ...
see also How can I use Reflection (Mirrors) to access the method names in a Dart Class?

Using dson you can do:
library example_lib;
import 'package:dson/dson.dart';
part 'main.g.dart';
#serializable
class Example extends _$ExampleSerializable {
Example() {
_callAll();
}
fn1() => print('fn1');
fn2() => print('fn2');
fn3() => print('fn3');
fn4() => print('fn4');
_callAll() {
reflect(this).methods.forEach((name, method) {
if(name != '_callAll') this[name]();
});
}
}
main(List<String> arguments) {
_initMirrors();
new Example();
}

Related

'Future<bool> Function()' can't be assigned to the parameter type 'Future<bool>?'

I'm trying to implement an event callback directly in the constructor, but for some reason it does not compile and I do not understand what's the issue with my code.
abstract class Base {
final Future<bool>? onMagic;
Base({
this.onMagic
});
Future<void> doSomething() async {
if(onMagic != null) {
// does not work... why?
// final useMagic = await onMagic!();
onMagic?.then((magic) {
if(magic) print("TODO make something magical");
});
}
}
}
class RealMagic extends Base {
RealMagic() : super(
// Error: The argument type 'Future<bool> Function()' can't be assigned to the parameter type 'Future<bool>?'.
onMagic: () async => await _magic();
);
Future<bool> _magic() async {
return true;
}
}
I inlined the error above. If that's not possible which alternatives do I have to handle the optional callback?
The problem is with the type of the onMagic. It's not a Future<bool>, it should be a Future<bool> Function()?
abstract class Base {
final Future<bool> Function()? onMagic;
Base({this.onMagic});
Future<void> doSomething() async {
onMagic?.call().then((magic) {
if (magic) print("TODO make something magical");
});
}
}
class RealMagic extends Base {
RealMagic()
: super(
onMagic: () async => await _magic(),
);
static Future<bool> _magic() async { // Made this static so it can be accessed in the constructor
return true;
}
}

Passing Class to Function

I’d like to pass the class User as second argument to the load-function.
Maybe someone knows how?
class App {
Map<String, List<Model>> models = {
'users': List<User>()
};
App() {
load('users');
}
void load(resource) {
Directory directory = Directory.fromUri(Uri(path: './app/data/' + resource));
for (FileSystemEntity file in directory.listSync(recursive: false)) {
Map<String, dynamic> fileContent = jsonDecode(File(file.uri.path).readAsStringSync());
models[resource].add(User.fromJson(fileContent));
}
}
}
You can't.
You can pass a Type object as argument, or a type as type argument (load<T>(resource) { ... }), but neither will allow you to call User.fromJson on the type.
What you can do is to pass the User.fromJson function as an argument (or, if that's a constructor, pass (x) => User.fromJson(x) as argument). That is:
void load(String resource, Object? fromJson(Map<String, dynamic> json)) {
...
map[resoruce].add(fromJson(fileContent));
}
and then
load("someName", (map) => User.fromJson(map));

Invoking nested functions in the Dart programming language

I defined an inner function here:
person(firstName, lastName){
fullName(){ //Is it possible to invoke this function outside the 'person' function?
return firstName + " " + lastName;
}
firstInitial(){
return firstName[0];
}
lastInitial(){
return lastName[0];
}
}
Next, I tried to invoke the "fullName" function from the "main" function:
void main() {
print(person("Rob", "Rock").fullName());
}
but it produced this error:
Uncaught TypeError: Cannot read property 'fullName$0' of undefined
Is it possible to invoke an inner function outside the scope where the function is defined?
You can declare the function outside the enclosing block:
void main() {
var fullName;
person(firstName, lastName){
fullName = () => "firstName: $firstName lastName: $lastName";
}
person("Rob", "Rock");
print(fullName());
}
or return it:
void main() {
person(firstName, lastName) => () => "firstName: $firstName"
"lastName: $lastName";
print(person("Rob", "Rock")());
}
If you want this syntax person("Rob", "Rock").fullName() you can return class instance:
class Res{
var _firstName, _lastName;
Res(this._firstName, this._lastName);
fullName() => "firstName: $_firstName lastName: $_lastName";
}
void main() {
person(firstName, lastName) => new Res(firstName,lastName);
print(person("Rob", "Rock").fullName());
}
Those functions can be invoked externally, the issue is that your program can't see them. Your function returns void, so the inner functions are invisible.
But what it looks like you're trying to do is define a class. So a simpler way to do it is
class Person {
var firstName, lastName;
Person(this.firstName, this.lastName);
get fullName => "$firstName $lastName";
firstInitial() => firstName[0];
lastInitial() { return lastName[0]; }
}
main() {
print(new Person("Rob", "Rock).fullName);
print(new Person("Robert", "Stone").lastInitial());
}
For illustration I used three different syntaxes for the three different functions, a getter, a lambda, and a full-blown function.

Other Classes in Class arguments

How can I set another Class as a Class constructor argument?
class MyClass {
String message = 'myClass';
void print() {
print(this.message);
}
}
class TestClass {
var myClass;
TestClass(???) {
this.myClass = ???(); // ???
}
void debug() {
print('DEBUG: ');
this.myClass.print();
}
}
main() {
MyClass myClass;
testClass(myClass);
}
You can't (at least not now). Your best option is to pass a builder function into the constructor.
class MyClass {
var clazzBuilder;
MyClass(this.clazzBuilder);
doStuff() {
var instance = clazzBuilder();
:
}
}
and then use it like this
var myTest = new MyClass(() => new Test());
var myProd = new MyClass(() => new Prod());
Note that the Dart team is planning to add both class concept (.type) and reflection to the language.
What do you want actually do? Often people try to apply paradigms from some languages in some other languages which isn't the best way to do some things.
Since print is an instance method and not a static method, you don't need to pass a class itself to TestClass, just an instance of it. Your program can be fixed like so:
class MyClass {
String message = 'myClass';
void print() {
print(this.message);
}
}
class TestClass {
var myClass;
TestClass(MyClass myClass) {
this.myClass = myClass;
}
void debug() {
print('DEBUG: ');
this.myClass.print();
}
}
main() {
MyClass myClass = new MyClass();
testClass(myClass);
}
Or, more idiomatically:
class MyClass {
String message = 'myClass';
void print() => print(message);
}
class TestClass {
var myClass;
TestClass(this.myClass);
void debug() {
print('DEBUG: ');
myClass.print();
}
}
main() {
testClass(new MyClass());
}

Inline Interface implementation in Actionscript

Is something like this possible in Actionscript?
Java:
URLFetcherFactory.setCreator(
new IURLFetcherCreator() {
public IURLFetcher create() {
return new URLFetcher();
}
}
);
Actionscript:
?
I've been wondering about this and have been unable to find anything that indicates it's possible. Figured if it was possible, I'd be able to find an answer here. Thanks! Stackoverflow rocks!
You cannot create an instance of an interface. You can, however, create a factory class:
public class URLFetcherCreator : IURLFetcherCreator {
private var _cls : Class;
public URLFetcherCreator(Class cls) {
this._cls = cls;
}
public function create() : IURLFetcher
{
return new cls();
}
}
Alternatively, change setCreator to accept a Function that returns an IURLFetcher:
URLFetcherFactory.setCreator(
function() : IURLFetcher {
return new URLFetcher();
}
);
Try this:
URLFetcherFactory.setCreator(
new IURLFetcherCreator() {
public function create():IURLFetcher {
return new URLFetcher();
}
}
);
You can't use anonymous inner classes in AS3.
For special cases like callbacks you can use Function instead of anonymous inner classes.
Java:
interface Callback {
void done(String info);
}
class Service {
void process(Callback callback);
}
...
myService.process(new Callback() {
void done(String info) {
// trace(info);
}
}
AS3:
class Service {
public function process(callback:Function):void;
}
...
myService.process(function(info:String):void {
trace(info);
});

Resources