2014-01-31 1 views
3

Я использую отражение (aka dart: mirror) в дротике. Во-первых: весь код, видимый здесь, отлично работает в dartium (с родным дартс), но только частично, когда скомпилирован с dart2js и выполняется в хроме.зеркала в дротике не работают для всех элементов

У меня есть класс под названием BinaryReader, чем чтение класса из байта. Вот код (раздел повторяющуюся часть), что делает так:

void readObject(dynamic obj) { 
    var inst = reflect(obj); 
    inst.type.declarations.forEach((Symbol name, DeclarationMirror decl) { 
     if(decl is VariableMirror) { 
     var variable = decl; 
     if(variable.metadata.length == 0) { 
      return; 
     } 

     InstanceMirror attrib = variable.metadata.first; 
     if(attrib.hasReflectee == false) { 
      return; 
     } 

     if(attrib.reflectee is Field) { 
      var field = attrib.reflectee as Field; 
      var value; 
      switch(field.type) { 
      case I8: 
       value = getInt8(); 
       break; 

      // ... 

      case V3: 
       value = new Vector3(getFloat(), getFloat(), getFloat()); 
       break; 

      default: 
       value = null; 
       break; 
      } 

      if(value == null) { 
      return; 
      } 

      inst.setField(name, value); 
     } 
     } 
    }); 
    } 

Импортирующих зеркала осуществляются следующим образом:

import 'model/M4SubMesh.dart'; 
import 'model/M4Model.dart'; 
import 'package:vector_math/vector_math.dart'; 
@MirrorsUsed(targets: const["M4SubMesh", "M4Model", "vector_math"], override: '*') 
import 'dart:mirrors'; 

M4SubMesh и M4Model имен библиотек соответствующего дротик файлов. vector_math один из vector_math.dart

Сначала я прочитал экземпляр M4Header, который является частью библиотеки M4Model из потока. Все значения являются правильными, вот как это выглядит:

class M4Header 
{ 
    @Field(UI32) 
    int Signature; 
    @Field(UI32) 
    int Version; 
    @Field(UI32) 
    int numSubMeshes; 
    @Field(UI32) 
    int ofsSubMeshes; 
} 

Тогда позже я стараюсь читать M4SubMeshHeader, который выглядит следующим образом:

class M4SubMeshHeader 
{ 
    @Field(UI32) 
    int gridX, gridY, gridZ; 
    @Field(F32) 
    num blockSize; 
    @Field(V3) 
    Vector3 bboxMin, bboxMax; 
} 

После прочтения BLOCKSIZE имеет случайное значение. bboxMin и bboxMax равны нулю. Что здесь происходит?

Приветствия Cromon

ответ

1

Найдено решение! Аннотация относится только к первому элементу в списке объявлений. Таким образом, в приведенном выше примере фактически расширен:

class M4SubMeshHeader 
{ 
    @Field(UI32) 
    int gridX; 
    int gridY; 
    int gridZ; 
    @Field(F32) 
    num blockSize; 
    @Field(V3) 
    Vector3 bboxMin; 
    Vector3 bboxMax; 
} 

На мой взгляд, это можно считать ошибкой, плохо взглянуть на документацию и если его там не упоминается об этом сообщить. Таким образом, в конце blockSize стало значением, которое должно было быть присвоено gridY, которое сделало его похожим на случайное. Но, честно говоря, я тоже должен взять на себя вину. 'bboxMin и bboxMax равны null', это неверно, bboxMin wasnt null, но имел недопустимые значения, но поскольку я оставил строку в коде, где я использовал bboxMax перед его печатью, я думал, что он уже сломался на bboxMin.

Приветствия Cromon

1

Я думает, что существует несоответствие между relection library и language specification.

Из спецификации языка:

«Метаданные могут появиться перед библиотекой, заголовок часть, класс, ЬурейеЕ, тип параметра, конструктор, фабрики, функции, поля, параметра, или переменной и перед импортом, экспортом или часть директивы ".

То есть, metadata может появиться перед variable declaration.

Теперь взгляните на определение variable declaration.

variableDeclaration: 
    declaredIdentifier (',' identifier)* 
    ; 
declaredIdentifier: 
    metadata finalConstVarOrType identifier 

То есть, variable declaration может состоять из следующих частей:

  • Метаданные, которые применяются к этой декларации.
  • final/const/var/type specifier
  • Список идентификаторов в этой декларации.

Это означает, что один variable declaration может объявлять неограниченное количество переменных.

Но это все равно будет одно объявление, но не так много разных деклараций в одном объявлении.

Это означает, что это variable declaration объявляет set of variables.

Также, если metadata может появиться до variable declaration, оно должно применяться ко всем элементам в этом объявлении.

Это потому, что, как указано в спецификации языка, metadata может появиться только до declaration, но не раньше part в этой декларации.

Это связано с тем, что в качестве спецификаций языка состояний у нас нет трехзначных объявлений переменных, кроме объявления ОДНОЙ переменной, которое объявило ТРЕХ переменных в этом объявлении.

var a, b, c; 

Итак, если эта переменная аннотирования декларация.

@Foo var a, b, c; 

Тогда, как спецификации состояния языка, если метаданные могут появляться перед тем объявлением переменной, то эти метаданные должны быть применены ко всей декларации, но не только к первому элементу в этой декларации.

P.S.

Это выводы, которые можно сделать на основе этого документа:

https://www.dartlang.org/docs/spec/latest/dart-language-specification.html

+0

Спасибо за вашу информацию, я принял мой ответ, потому что его решение, пока ваш ответ более очень интересное понимание того, как он не должно быть так, я надеюсь, что это нормально для вас. – Cromon

+0

Мой ответ потребовал разъяснений от экспертов Dart. В настоящее время такие нюансы встречаются повсюду. Существует много примеров, подтверждающих, что даже сами разработчики часто не имеют представления о том, как следует толковать те или иные двусмысленные действия. Чем меньше проблем людей затрагивает меньший интерес, тем больше проявляются разработчики в этой проблеме. Таким образом, вы нашли решение, и это означает, что это не проблема. То есть сама проблема может быть не проблемой, если она по-прежнему не создает экспоненциально других проблем, даже если проблема является неправильным поведением. Это основное правило разработчиков Dart. – mezoni

 Смежные вопросы

  • Нет связанных вопросов^_^