【问题标题】:mirrors in dart not working for all elements飞镖中的镜子不适用于所有元素
【发布时间】:2014-01-31 20:09:50
【问题描述】:

我在 dart 中使用反射(又名 dart:mirrors)。首先:这里看到的所有代码都在 dartium 中完美运行(使用 dart 本机),但只有部分使用 dart2js 编译并在 chrome 中运行。

我有一个名为 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 是各自 dart 文件的库名称。 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 为空。这里出了什么问题?

问候 克罗蒙

【问题讨论】:

    标签: javascript dart dart-mirrors


    【解决方案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 为空',这是错误的,bboxMin 不是空的,但具有无效值,但是当我在打印之前使用 bboxMax 的代码中留下一行时,我认为它已经在 bboxMin 处损坏了。

    问候 克罗蒙

    【讨论】:

      【解决方案2】:

      我认为relection library 和language specification 之间存在不匹配。

      来自语言规范:

      “元数据可以出现在库、部件标题、类、typedef、类型参数、构造函数、工厂、函数、字段、参数或变量声明之前以及导入、导出或部件指令之前”。

      即metadata可以出现在variable declaration之前。

      现在看看variable declaration 的定义。

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

      也就是说,variable declaration 可能由以下部分组成:

      • 应用于此声明的元数据。
      • final/const/var/类型说明符
      • 此声明中的标识符列表。

      这意味着一个variable declaration 可以声明无限数量的变量。

      但它仍然是一个声明,但在一个声明中不会有很多不同的声明。

      这只意味着这个variable declaration声明了一个set of variables。

      此外,如果metadata 可以出现在variable declaration 之前,则它必须应用于此声明中的所有元素。

      这是因为,按照国家语言规范,metadata 只能出现在此声明中的 declaration 之前,但不能出现在某些 part 之前。

      这是因为,按照语言规范,我们没有三个变量声明,而是一个变量声明,在此声明中声明了三个变量。

      var a, b, c;
      

      所以,如果注释这个变量声明。

      @Foo var a, b, c;
      

      然后,正如语言规范所述,如果元数据可以出现在变量声明之前,那么该元数据必须应用于整个声明,而不仅仅是该声明中的第一个元素。

      附言

      根据本文档可以得出的结论:

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

      【讨论】:

      • 感谢您的信息,我接受了我的回答,因为它是解决方案,而您的回答是关于它不应该是这样的更有趣的见解,我希望这对您来说没问题。跨度>
      • 我的回答需要 Dart 专家的澄清。目前,这样的细微差别无处不在。有许多例子证实,即使是开发人员自己也常常不知道应该如何解释这个或那个模棱两可的行为。受影响的人越少,开发人员对这个问题的兴趣就越小。所以你找到了解决方案,这意味着这不是问题。也就是说,即使问题是不正确的行为,如果它仍然不会产生指数级的其他问题,问题本身就不是问题。这是 Dart 开发人员的主要规则。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-17
      • 2020-02-17
      • 2019-11-05
      • 1970-01-01
      • 2014-12-04
      相关资源
      最近更新 更多