What can i do with a stored type? - dart

Dart allows variables of types: Type type = SomeType; But for what purpose?
For example, foo bar baz are misapplications:
class A {
Type type = List;
foo() => new type();
type bar() {
return new List();
}
type baz = new List();
}
void main() {
Type type = String;
var str = "Hello Dart";
print(type == str.runtimeType);//true
print(str is String);//true
print(str is type); //type error.
}
I think this one is pretty neat:
void main() {
foo(Type t) {
switch (t){
case int: return 5;
case List: return [1,2,3]; // This one gets me every time :(
case String: return "Hello Dart!";
default: return "default";
}}
print(foo(10.runtimeType)); //5
print(foo([2,4,6].runtimeType)); //default
print(foo("lalala".runtimeType)); //Hello Dart!
print(foo(foo.runtimeType)); //default
}
Is its sole purpose to be the return type for methods like runtimeType and type matching ?

I don't think you can use it for generics. There you need type literals. But you can use it for reflection.
Just one simple example:
import 'dart:mirrors' as mirr;
class A {
String s;
A(this.s);
#override
String toString() => s;
}
void main() {
Type type = A;
var str = "Hello Dart";
mirr.ClassMirror cm = mirr.reflectType(type);
var s = cm.newInstance(new Symbol(''), [str]).reflectee;
print(s);
}
You could also create a Map with registered factories for different types to avoid the need for reflection.
(not tested)
class A {
String s;
int a = 0;
int b = 0;
int c = 0;
A(this.s);
A.extended(this.s, this.a, this.b, this.c);
#override
String toString() => '${super.toString()}: $s, $a, $b, $c';
}
void main(args) {
Type t = A;
registerType(t, (List args) => new A.extended(args[0], args[1], args[2], args[3]));
...
var a = getInstance(t, ['hallo', 1, 2, 3]);
}
Map<Type,Function> _factories = {};
void registerType(Type t, Function factory) {
_factories[t] = factory;
}
void getNewInstance(Type t, List args) {
return _factories[t](args);
}

Related

How to dynamically instantiate a class (Function.apply for class)?

In Dart, I can dynamically call a function using Function.apply:
Function.apply(foo, [1,2,3], {#f: 4, #g: 5});
gives exactly the same result as
foo(1, 2, 3, f: 4, g: 5).
Question: Does a similar thing exist for instantiating classes?
Expected result would look something like:
class foo {
final String boo;
int? moo;
foo({required this.boo, this.moo})
}
...
var params = {boo: 'A string value', moo: 121};
Class.apply(foo, params);
// Gives the result:
foo(boo: 'A string value', moo: 121);
Function.apply isn't type-safe, so you should avoid using it if you can.
If you really want to use it with a constructor, you can use it with constructor tear-offs (added in Dart 2.15), which are just Functions:
class Foo {
final String boo;
int? moo;
Foo({required this.boo, this.moo});
#override
String toString() => 'Foo(boo: "$boo", moo: $moo)';
}
void main() {
var params = {#boo: 'A string value', #moo: 121};
var result = Function.apply(Foo.new, [], params);
print(result); // Prints: Foo(boo: "A string value", moo: 121)
}
As far as I know, you can make use of static methods if you want to create an instance without using another instance. Here is a sample:
class Foo {
final String boo;
final int moo;
Foo({this.boo, this.moo});
static fromValues({String boo, int moo}) {
return Foo(boo: boo, moo: moo);
}
}
void main() {
var params = {#boo: 'A string value', #moo: 121};
var fooObject = Function.apply(Foo.fromValues, [], params);
print(fooObject);
print(fooObject.boo);
print(fooObject.moo);
}
Another way is to add 'call' function to class to make it's objects callable and use an object of the class to create new objects. Here is a sample:
class Foo {
final String boo;
final int moo;
Foo({this.boo, this.moo});
call({String boo, int moo}) {
return Foo(boo: boo, moo: moo);
}
}
void main() {
Foo aFoo = Foo(boo: 'nothing', moo: 0);
var params = {#boo: 'A string value', #moo: 121};
var fooObject = Function.apply(aFoo, [], params);
print(fooObject);
print(fooObject.boo);
print(fooObject.moo);
}

How to convert a GLib.Value of type GStrv (string[]) to a GLib.Variant

In the following example one class property is of type Gstrv.
With ObjectClass.list_properties() one can query the Paramspec of all properties, and with get_property() all properties can be requested as GLib.Value. How would I access the Value of type GStrv and convert it to a GLib.Variant?
My GLib version is slightly outdated, so I do not have the GLib.Value.to_variant() function available yet :( .
public class Foo: GLib.Object {
public GLib.HashTable<string, int32> bar;
public Foo() {
bar = new GLib.HashTable<string, int32>(str_hash, str_equal);
}
public string[] bar_keys { owned get { return bar.get_keys_as_array(); } }
}
int main() {
var foo = new Foo();
Type type = foo.get_type();
ObjectClass ocl = (ObjectClass) type.class_ref ();
foreach (ParamSpec spec in ocl.list_properties ()) {
print ("%s\n", spec.get_name ());
Value property_value = Value(spec.value_type);
print ("%s\n", property_value.type_name ());
foo.get_property(spec.name, ref property_value);
// next: convert GLib.Value -> GLib.Variant :(
}
foo.bar.set("baz", 42);
return 0;
}
Output:
bar-keys
GStrv
Using GLib.Value.get_boxed() seems to be working.
Example:
// compile simply with: valac valacode.vala
public class Foo: GLib.Object {
public GLib.HashTable<string, int32> bar;
public Foo() {
bar = new GLib.HashTable<string, int32>(str_hash, str_equal);
}
public string[] bar_keys { owned get { return bar.get_keys_as_array(); } }
}
public Variant first_gstrv_property_as_variant(Object obj)
{
Type class_type = obj.get_type();
ObjectClass ocl = (ObjectClass) class_type.class_ref ();
foreach (ParamSpec spec in ocl.list_properties ()) {
print ("%s\n", spec.get_name ());
Value property_value = Value(spec.value_type);
print ("%s\n", property_value.type_name ());
obj.get_property(spec.name, ref property_value);
// next: convert GLib.Value -> GLib.Variant
if(property_value.type_name () == "GStrv") {
return new GLib.Variant.strv((string[])property_value.get_boxed());
}
}
return new GLib.Variant("s", "No property of type GStrv found");
}
int main() {
var foo = new Foo();
print("%s\n", first_gstrv_property_as_variant(foo).print(true));
foo.bar.set("baz", 42);
print("%s\n", first_gstrv_property_as_variant(foo).print(true));
foo.bar.set("zot", 3);
print("%s\n", first_gstrv_property_as_variant(foo).print(true));
return 0;
}
Output:
bar-keys
GStrv
#as []
bar-keys
GStrv
['baz']
bar-keys
GStrv
['baz', 'zot']
In the generated c-code this looks as follows:
_tmp18_ = g_value_get_boxed (&property_value);
_tmp19_ = g_variant_new_strv ((gchar**) _tmp18_, -1);
Passing -1 as length to g_variant_new_strv() means the string array is considered as null terminated. Inside g_variant_new_strv() the g_strv_length() function is used to determine the length.
Hopefully it will be useful to someone else someday. :-)

Unable to cast an F# Object in C#

Given this F#:
namespace DU_Sample
type StateA = { Counter: int }
type StateB = { Counter: int; Pass: bool }
type DU =
| A of StateA
| B of StateB
And this C#:
[TestMethod]
public void TestMethod1()
{
var stateB = GetStateB();
Assert.IsTrue( stateB.IsB );
//Assert.IsTrue( ((DU_Sample.StateB)stateB).Pass ); // nope
//var nutherB = DU_Sample.DU.NewB( stateB ); // nope
Assert.IsTrue( ( (dynamic)stateB ).Item.Pass ); // pass
}
private static DU_Sample.DU GetStateB()
{
var stateB = new DU_Sample.StateB( 0, true );
return DU_Sample.DU.NewB( stateB );
}
How can I cast the Discriminated Union type to one of it's parts in order to access that part's properties?
In both cases you have to (down) cast and then use the property Item:
Assert.IsTrue((stateB as DU_Sample.DU.B)?.Item.Pass ?? false);
var nutherB = DU_Sample.DU.NewB(((DU_Sample.DU.B)stateB).Item)

How do I get all the fields of an object (including its superclass), using Dart's Mirrors API?

Given two Dart classes like:
class A {
String s;
int i;
bool b;
}
class B extends A {
double d;
}
And given an instance of B:
var b = new B();
How do I get all the fields in the b instance, including fields from its superclass?
Use dart:mirrors!
import 'dart:mirrors';
class A {
String s;
int i;
bool b;
}
class B extends A {
double d;
}
main() {
var b = new B();
// reflect on the instance
var instanceMirror = reflect(b);
var type = instanceMirror.type;
// type will be null for Object's superclass
while (type != null) {
// if you only care about public fields,
// check if d.isPrivate != true
print(type.declarations.values.where((d) => d is VariableMirror));
type = type.superclass;
}
}
import 'dart:mirrors';
class Test {
int a = 5;
static int s = 5;
final int _b = 6;
int get b => _b;
int get c => 0;
}
void main() {
Test t = new Test();
InstanceMirror instance_mirror = reflect(t);
var class_mirror = instance_mirror.type;
for (var v in class_mirror.declarations.values) {
var name = MirrorSystem.getName(v.simpleName);
if (v is VariableMirror) {
print("Variable: $name => S: ${v.isStatic}, P: ${v.isPrivate}, F: ${v.isFinal}, C: ${v.isConst}");
} else if (v is MethodMirror) {
print("Method: $name => S: ${v.isStatic}, P: ${v.isPrivate}, A: ${v.isAbstract}");
}
}
}

Dart: How to convert variable identifier names to strings only for variables of a certain type

Using Dart here.
As the above title suggests, I have a class (shown below) that has three bool instance variables. What I want to do is create a function that inspects the identifier names of these instance variables and prints each of them out in a string. The .declarations getter that comes with the ClassMirror class ALMOST does this, except it also gives me the name of the Constructor and any other methods I have in the class. This is no good. So really what I want is a way to filter by type (i.e., only give me the boolean identifiers as strings.) Any way to do this?
class BooleanHolder {
bool isMarried = false;
bool isBoard2 = false;
bool isBoard3 = false;
List<bool> boolCollection;
BooleanHolder() {
}
void boolsToStrings() {
ClassMirror cm = reflectClass(BooleanHolder);
Map<Symbol, DeclarationMirror> map = cm.declarations;
for (DeclarationMirror dm in map.values) {
print(MirrorSystem.getName(dm.simpleName));
}
}
}
OUTPUT IS:
isMarried
isBoard2
isBoard3
boolsToStrings
BooleanHolder
Sample code.
import "dart:mirrors";
void main() {
var type = reflectType(Foo);
var found = filter(type, [reflectType(bool), reflectType(int)]);
for(var element in found) {
var name = MirrorSystem.getName(element.simpleName);
print(name);
}
}
List<VariableMirror> filter(TypeMirror owner, List<TypeMirror> types) {
var result = new List<VariableMirror>();
if (owner is ClassMirror) {
for (var declaration in owner.declarations.values) {
if (declaration is VariableMirror) {
var declaredType = declaration.type;
for (var type in types) {
if (declaredType.isSubtypeOf(type)) {
result.add(declaration);
}
}
}
}
}
return result;
}
class Foo {
bool bool1 = true;
bool bool2;
int int1;
int int2;
String string1;
String string2;
}
Output:
bool1
bool2
int1
int2

Resources