元数据
本章节将讨论Dart的元数据注解及其自定义,以及使用 mirors 包获取元数据等信息。
注解
元数据(metadata)用于给代码添加额外的信息,元数据注解(annotation,以下简称注解)以 @ 字符开头,后接一个常量值。我们在之前的代码中已多次见过 @override,它表示实例成员的重写,通常是一个类重写/实现了某个方法。
// ex412.dart
base class Vehicle { // 1
void moveForward(int meters) {
// ...
}
}
base class Car implements Vehicle { // 2
@override
void moveForward(int meters) {
// ...
}
}
以下4个注解对所有的Dart代码可用:
@override@Deprecated@deprecated@pragma
@Deprecated 标记某个功能已过时。
// ex481.dart
class Motorcycle {
/// Use [start] instead
@Deprecated('Use start instead')
void ignite() {
start();
}
/// Start the engine
void start() {
// ...
}
}
@deprecated (注意首字母d小写),不携带附加的信息(message);事实上从源码中可以看出,它的message 被硬编码为"next release"。
// dart-sdk/lib/core/annotations.dart
const Deprecated deprecated = Deprecated("next release");
@pragma 用于与Dart程序协同工作的工具。
自定义注解
可以像下面这样自定义注解。
// ex482.dart
class Table { // 1
final String name;
final String pk;
const Table(this.name, {required this.pk}); // 2
}
@Table('tb_staff', pk: 'id') // 3
class Staff {
int id;
String name;
List<String> skills;
Staff(this.id, {required this.name, this.skills = const []});
}
- 这是一个普通的类
Table,其实例变量name表示表名,pk表示主键 ; Table提供了一个常量构造器,对于注解这是必须的;- 使用注解
@Table对Staff类进行标记。
使用 mirrors
mirrors 包是Dart中的反射工具,类似Java中的java.lang.reflect。mirrors中的3个反射函数:
// dart-sdk/lib/mirrors/mirrors.dart
external InstanceMirror reflect(dynamic reflectee);
external ClassMirror reflectClass(Type key);
external TypeMirror reflectType(Type key, [List<Type>? typeArguments]);
reflect 反射一个实例,reflectClass 反射一个类,reflectType 反射一个类型。到底什么是反射(reflection)?下面通过一个示例来说明。
// ex483.dart
import 'dart:mirrors';
class _Foo {
const _Foo();
}
class _Bar {
const _Bar();
}
const foo = _Foo();
const bar = _Bar();
@foo
@bar
class Exam {
@foo
String? str;
@bar
void exam() {}
}
void main() {
var examMirror = reflectClass(Exam); // 1
for (var meta in examMirror.metadata) { // 2
print(meta.reflectee);
}
// Output:
// Instance of 'Foo'
// Instance of 'Bar'
for (var mem in examMirror.instanceMembers.entries) {
print(mem); // 3
print(' metadata: ${mem.value.metadata}'); // 4
}
// Output:
// MapEntry(Symbol("=="): MethodMirror on '==')
// metadata: [InstanceMirror on Instance of '_Patch', InstanceMirror on Instance of 'pragma', InstanceMirror on Instance of 'pragma', InstanceMirror on Instance of 'pragma', InstanceMirror on Instance of 'pragma']
// MapEntry(Symbol("hashCode"): MethodMirror on 'hashCode')
// metadata: [InstanceMirror on Instance of '_Patch']
// MapEntry(Symbol("toString"): MethodMirror on 'toString')
// metadata: [InstanceMirror on Instance of '_Patch', InstanceMirror on Instance of 'pragma']
// MapEntry(Symbol("noSuchMethod"): MethodMirror on 'noSuchMethod')
// metadata: [InstanceMirror on Instance of 'pragma', InstanceMirror on Instance of 'pragma', InstanceMirror on Instance of '_Patch', InstanceMirror on Instance of 'pragma']
// MapEntry(Symbol("runtimeType"): MethodMirror on 'runtimeType')
// metadata: [InstanceMirror on Instance of '_Patch', InstanceMirror on Instance of 'pragma', InstanceMirror on Instance of 'pragma']
// MapEntry(Symbol("str"): Instance of '_SyntheticAccessor')
// metadata: []
// MapEntry(Symbol("str="): Instance of '_SyntheticAccessor')
// metadata: []
// MapEntry(Symbol("exam"): MethodMirror on 'exam')
// metadata: [InstanceMirror on Instance of '_Bar']
}
- 反射
Exam类; Exam类的元数据;- 获取
Exam类的实例成员; - 获取
Exam类的实例成员的元数据。