Issue
Trying to access a private (package internal) field got me in a strange situation.
My Class “Properties” has a internal field named ‘_forceAccum’.
Trying to get the value of it fails for me using this code:
InstanceMirror bodyMirror = reflect(props);
var value = propsMirror.getField(new Symbol('_forceAccum'));
but if I use this instead:
InstanceMirror bodyMirror = reflect(props);
var value = propsMirror.getField(new Symbol('_forceAccum@434525364'));
it works. (I got the “@…” from iterating through the symbols (.toString()) from the class mirror).
Is it supposed to work this way? Is it safe or will it change in the next version? (I’m using 1.7.2)
or does it just work by pure happenstance?
Solution
Your problem is that you have a library private name. It’s name isn’t just _forceAccum
, it’s a special symbol related to _forceAccum
that is unique to the library, but different from a _forceAccum
in another library.
To create the private symbol using mirrors, you must use MirrorSystem.getSymbol as: MirrorSystem.getSymbol("_forceAccum", libraryMirrorOfLibrary)
. This creates a library-private symbol for that particular library. You can’t create a private symbol without either specifying the library that it’s private to, or by being in the library (#_forceAccum
will create the correct symbol for the library that it occurs in).
The other alternative, which you used, is to look through the library and find the already existing symbol there:
var forceAccumSymbol =
libraryMirrorOfLibrary.declarations.keys
.where((n) => MirrorSystem.getName(n) == "_forceAccum")
.first;
(if the declaration is a top-level declaration).
The _forceAccum@something
name that you are seeing is the VM’s way of making a name library private. It’s not going to work if compiled with dart2js, and it’s probably not going to have the same something
on each run, so you can’t can’t put it into your code.
Answered By – lrn
Answer Checked By – Timothy Miller (FlutterFixes Admin)