This tutorial shows you how to get all fields and methods in a class using Dart reflection library (mirrors).
In Object-Oriented Prorgramming where we can use and create classes, sometimes it's necessary to know what variables and methods does a class have. If you are using Dart and you need to get the list of fields (variables) and methods for a class, you can use Dart's reflection library by importing dart:mirrors
.
For example, there are two classes: Product
and Computer
, the latter extends the former.
class Product {
final String name;
final String description;
const Product(this.name, this.description);
}
class Computer extends Product {
final String processor;
final String memory;
Computer(name, description, this.processor, this.memory) : super(name, description);
}
First, create an instance of the class - in this example, the Computer
class. To use the reflection library, we need to get InstaneMirror
by using reflect
.
InstanceMirror reflect(Object reflectee);
Then, get the ClassMirror
by accessing type
property of the InstanceMirror.
Example:
Computer computer = new Computer(
'Computer One',
'No longer used',
'Dual-core',
'1GB'
);
InstanceMirror im = reflect(computer);
ClassMirror classMirror = im.type;
After getting the ClassMirror
instance, we can get the data member list using Mirror.declarations.values
. Then, iterate through the list to get all fields (variables) and methods. The name for each data member can be obtained using MirrorSystem.getName
as examplified below.
for (var v in classMirror.declarations.values) {
var name = MirrorSystem.getName(v.simpleName);
}
To check the what kind of data member is being iterated, whether it's a variable or method, use v is VariableMirror
and v is MethodMirror
respectively. You may need to handle them differently as they have different properties. If you use if
block like the below code, the runtimeType
of v
inside the if
block will be the class used on the right hand side of is
. Therefore, you can access the fields of the corresponding class.
Keep in mind that the mirror of a constructor is a MethodMirror
. However, you can easily distinguish constructor using isConstructor
field. The list of fields for VariableMirror
and MethodMirror
can be seen on the bottom of this tutorial.
if (v is VariableMirror) {
// Handle if data member is a variable
} else if (v is MethodMirror) {
// Handle if data member is a method
}
With the code above, you'll only get the data members of the current class. To get the data members of the parent class, you need to get the ClassMirror
of the parent class first.
ClassMirror superClassMirror = classMirror.superclass;
Below is the full code. There is a function getDataMembers
which is used for getting the data members of Computer
class and its superclass (Product
).
import 'dart:mirrors';
class Product {
final String name;
final String description;
const Product(this.name, this.description);
}
class Computer extends Product {
final String processor;
final String memory;
Computer(name, description, this.processor, this.memory) : super(name, description);
}
void getDataMembers(ClassMirror classMirror) {
for (var v in classMirror.declarations.values) {
var name = MirrorSystem.getName(v.simpleName);
if (v is VariableMirror) {
print('Variable: $name');
print('const: ${v.isConst}');
print('final: ${v.isFinal}');
print('private: ${v.isPrivate}');
print('static: ${v.isStatic}');
print('extension: ${v.isExtensionMember}');
} else if (v is MethodMirror) {
print('Method: $name');
print('abstract: ${v.isAbstract}');
print('private: ${v.isPrivate}');
print('static: ${v.isStatic}');
print('extension: ${v.isExtensionMember}');
print('constructor: ${v.isConstructor}');
print('top level: ${v.isTopLevel}');
}
print('-----------------------------');
}
}
void main() {
Computer computer = new Computer(
'Computer One',
'No longer used',
'Dual-core',
'1GB'
);
InstanceMirror im = reflect(computer);
ClassMirror classMirror = im.type;
getDataMembers(classMirror);
// Get data members of superclass
ClassMirror superClassMirror = classMirror.superclass;
if (superClass != null) {
getDataMembers(superClassMirror);
}
}
That's how to get the data members of a class.
Getters of MethodMirror
Name | Type | Description |
---|---|---|
returnType |
bool |
A mirror on the return type for the reflectee. |
source |
String |
Source code for the reflectee. |
parameters |
List<ParameterMirror> |
List of mirrors on the parameters for the reflectee. |
isStatic |
bool |
Whether the reflectee is static. |
isAbstract |
bool |
Whether the reflectee is abstract. |
isSynthetic |
bool |
Whether the reflectee is a synthetic (a getter or setter implicitly introduced for a field or Type, or a constructor that was implicitly introduced as a default constructor). |
isRegularMethod |
bool |
Whether the reflectee is a regular method (not a getter, setter, or constructor). |
isOperator |
bool |
Whether the reflectee is an operator. |
isGetter |
bool |
Whether the reflectee is a getter. |
isSetter |
bool |
Whether the reflectee is a setter. |
isConstructor |
bool |
Whether the reflectee is a constructor. |
isConstConstructor |
bool |
Whether the reflectee is a const constructor. |
isGenerativeConstructor |
bool |
Whether the reflectee is a generative constructor. |
isRedirectingConstructor |
bool |
Whether the reflectee is a redirecting constructor. |
isFactoryConstructor |
bool |
Whether the reflectee is a factory constructor. |
constructorName |
String |
Name of the constructor for named constructors and factory methods. |
isExtensionMember |
bool |
Whether the reflectee is an extension member. |
==(other) |
bool |
Compare whether the reflectee is equal to other . |
Getters of VariableMirror
Name | Type | Description |
---|---|---|
type |
TypeMirror |
Type of the reflectee. |
isStatic |
bool |
Whether the reflectee is a static variable. |
isFinal |
bool |
Whether the reflectee is a final variable. |
isConst | bool |
Whether the reflectee is declared as const . |
isExtensionMember |
bool |
Whether the reflectee is an extension member. |
==(other) |
bool |
Compare whether the reflectee is equal to other . |