2

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.

Kiva
  • 9,193
  • 17
  • 62
  • 94

2 Answers2

1

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)}');
  }
}
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • Badly, it doesn't work, maybe I'm doing something wrong. I edit my post with my code – Kiva Apr 02 '14 at 20:49
  • The key from `declarations` didn't work for me either (same error). But using `declaration.simpleName` or one of the other two (commented out) variants to create a symbol for a private field worked for me. – Günter Zöchbauer Apr 03 '14 at 03:59
0

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']}");
}
Luis Vargas
  • 2,466
  • 2
  • 15
  • 32