我在飞镖中使用反射(又名飞镖:镜子)。第一:这里看到的所有代码在dartium(使用dart native)中完美运行,但在使用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为null。这里出了什么问题?
问候 Cromon
答案 0 :(得分: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不是null,但是有无效的值,但是我在代码中留下了一行,我在打印之前使用了bboxMax,我认为它已经在bboxMin中破坏了。
问候 Cromon
答案 1 :(得分:1)
我认为relection library
和language specification
之间存在不匹配。
来自语言规范:
“元数据可以出现在库,部件标题,类,typedef,类型参数,构造函数,工厂,函数,字段,参数或变量声明之前以及导入,导出或部件指令之前”。
也就是说,metadata
可以出现在variable declaration
之前。
现在看看variable declaration
定义。
variableDeclaration:
declaredIdentifier (',' identifier)*
;
declaredIdentifier:
metadata finalConstVarOrType identifier
也就是说,variable declaration
可能包含以下部分:
这意味着一个variable declaration
可以声明无限数量的变量。
但它仍然是一个声明,但在一个声明中没有多少不同的声明。
这仅表示此variable declaration
声明了set of variables
。
此外,如果metadata
出现在variable declaration
之前,则必须将其应用于此声明中的所有元素。
这是因为,作为州语言规范,metadata
只能出现在declaration
之前,而不能出现在此声明中的某些part
之前。
这是因为,作为状态语言规范,我们没有THREE变量声明,而是在此声明中声明了THREE变量的ONE变量声明。
var a, b, c;
所以,如果注释这个变量声明。
@Foo var a, b, c;
然后,作为状态语言规范,如果元数据可以在变量声明之前出现,则此元数据必须应用于整个声明,但不仅应用于此声明中的第一个元素。
P.S。
这个结论可以在这个文件的基础上做出:
https://www.dartlang.org/docs/spec/latest/dart-language-specification.html