Этот образец более безопасны, потому что выполнять дополнительные операции:
- Запрос только указанные элементы типа.
- Выполните проверки совместимости типов.
- Попробуйте преобразовать значения.
import 'package:reflection/reflection.dart';
class ObjectFiller {
static void fill(Object obj, Map map) {
var ti = typeInfo(obj.runtimeType);
// Query only specified type members
for(VariableInfo vi in ti.getVariables(BindingFlags.PUBLIC |
BindingFlags.INSTANCE).values) {
var name = SymbolHelper.getName(vi.simpleName);
if(map.containsKey(name)) {
var value = map[name];
// Perform type compatibility checks.
if(typeInfo(value.runtimeType).isAssignableFrom(vi.type)) {
vi.setValue(obj, value);
} else {
// Try convert values.
if(value is String) {
if(typeInfo(int).isAssignableFrom(vi.type)) {
try {
vi.setValue(obj, int.parse(value));
} catch(e) {
}
}
}
}
}
}
}
}
void main() {
var objects = [];
// null object
objects.add([null, {"foo" : 41}]);
// Zebra object (without one front tooth)
// Slipped, fell, woke up - one tooth missing
objects.add([new Zebra(), {"numberOfTeeth" : "43", "numberOfStripes" : 30}]);
// Zebra object
objects.add([new Zebra(), {"numberOfTeeth" : 44, "numberOfStripes" : 40}]);
// Filling objects
for(var object in objects) {
ObjectFiller.fill(object[0], object[1]);
}
// Dumping objects (full)
for(var object in objects) {
var obj = object[0];
print("Full dump of ${obj}");
print(objectToMap(obj));
print("---------------------------");
}
// Dumping objects (short)
for(var object in objects) {
var obj = object[0];
print("Short dump of ${obj}");
print(objectToMap(obj, true));
print("---------------------------");
}
}
Map objectToMap(Object obj, [bool declaredOnly = false]) {
var map = {};
if(obj == null) {
return map;
}
var flags = BindingFlags.PUBLIC | BindingFlags.INSTANCE;
if(declaredOnly) {
flags |= BindingFlags.DECLARED_ONLY;
}
var ti = typeInfo(obj.runtimeType);
for(VariableInfo vi in ti.getVariables(flags).values) {
var name = SymbolHelper.getName(vi.simpleName);
map[name] = vi.getValue(obj);
}
for(PropertyInfo pi in ti.getProperties(flags).values) {
if(pi.isGetter) {
var name = SymbolHelper.getName(pi.simpleName);
map[name] = pi.getValue(obj);
}
}
return map;
}
abstract class Animal {
static String unusedInAnimal;
int numberOfTeeth = 0;
String get family;
}
class Zebra extends Animal {
static String unusedInZebra;
int numberOfStripes = 0;
String get family => "Equidae";
}
Full dump of null
{}
---------------------------
Full dump of Instance of 'Zebra'
{numberOfTeeth: 43, numberOfStripes: 30, hashCode: 970552119, runtimeType: Zebra, family: Equidae}
---------------------------
Full dump of Instance of 'Zebra'
{numberOfTeeth: 44, numberOfStripes: 40, hashCode: 1024653070, runtimeType: Zebra, family: Equidae}
---------------------------
Short dump of null
{}
---------------------------
Short dump of Instance of 'Zebra'
{numberOfStripes: 30, family: Equidae}
---------------------------
Short dump of Instance of 'Zebra'
{numberOfStripes: 40, family: Equidae}
---------------------------
Есть ли способ, чтобы получить все наследуемые поля без прогулки по иерархии? –
Думаю, вам нужно пройти через иерархию. –