2014-01-05 3 views
4

Я динамически создаю объекты из данных карты, заполняя поля для сопоставления имен ключей. Проблема возникает, когда поля определены на родителе, где пытается установить значение на родительском поле вызывает ошибку:Динамическое заполнение родительского поля в Dart

No static setter 'name' declared in class 'Skill'. 

    NoSuchMethodError : method not found: 'name' 

код:

class Resource { 
    String name; 
    String description; 

    Resource.map(Map data) 
    { 
    ClassMirror c = reflectClass(runtimeType); 
    ClassMirror thisType = c; 
    while(c != null) 
    { 
     for (var k in c.declarations.keys) { 
     print('${MirrorSystem.getName(k)} : ${data[MirrorSystem.getName(k)]}'); 
     if(data[MirrorSystem.getName(k)] != null) 
     { 
      thisType.setField(k, data[MirrorSystem.getName(k)]);   
     } 
     } 
     c = c.superclass; 
    } 
    } 
} 

class Skill extends Resource 
{ 
    Skill.map(data) : super.map(data); 
} 

ответ

4

Вы должны используйте поле ObjectMirror, чтобы установить поле на вашем объекте. Ваш код пытается установить поле на ClassMirror, которое пытается определить статическую переменную .

class Resource { 
    String name; 
    String description; 

    Resource.map(Map data) 
    { 
    ObjectMirror o = reflect(this); // added 
    ClassMirror c = reflectClass(runtimeType); 
    ClassMirror thisType = c; 
    while(c != null) 
    { 
     for (var k in c.declarations.keys) { 
     print('${MirrorSystem.getName(k)} : ${data[MirrorSystem.getName(k)]}'); 
     if(data[MirrorSystem.getName(k)] != null) 
     { 
      // replace "thisType" with "o" 
      o.setField(k, data[MirrorSystem.getName(k)]); 
     } 
     } 
     c = c.superclass; 
    } 
    } 
} 

class Skill extends Resource 
{ 
    Skill.map(data) : super.map(data); 
} 
+0

Есть ли способ, чтобы получить все наследуемые поля без прогулки по иерархии? –

+0

Думаю, вам нужно пройти через иерархию. –

2

Статические методы/поля не наследуется Dart ,
Здесь уже были некоторые дискуссии об этом поведении.
Вы можете посмотреть на ответ на этот вопрос in Dart, using Mirrors, how would you call a class's static method from an instance of the class?

Если методы/поля вы пытаетесь получить доступ, не являются статичными просьба предоставить больше кода (классы/объекты, которые отражают около)

1

Этот образец более безопасны, потому что выполнять дополнительные операции:

  • Запрос только указанные элементы типа.
  • Выполните проверки совместимости типов.
  • Попробуйте преобразовать значения.
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} 
---------------------------