Mirrors
Mirrors is a lightweight static reflection library for Dart, using code generation.
It is designed as a modern alternative to reflectable.
Installation
Add the following to your pubspec.yaml:
dependencies:
mirrors: ^1.0.0
dev_dependencies:
mirror_builder: ^1.0.0
build_runner: ^2.4.0
Usage
Unlike dart:mirrors, this library requires you to be explicit about what capabilities you want to enable (methods,
fields, constructors, etc.) to keep the generated code size small.
1. Define your Reflection Strategy
Create a constant class that extends Mirrors and implements the capabilities you need. You can use AllCapability for full access or pick specific interfaces like MethodsCapability or FieldsCapability.
import 'package:mirror/mirror.dart';
// Create a custom annotation that defines your reflection capabilities
class Mirrored extends Mirrors implements AllCapability {
const Mirrored();
}
// Or, for a more restrictive configuration:
// class Reflector extends Mirrors implements MethodsCapability, GettersCapability {
// const Reflector();
// }
2. Annotate your code
Use your custom annotation (e.g., @Mirrored) to mark classes, enums, or functions for reflection.
// Use the annotation you defined in Step 1
@Mirrored()
class Todo {
final String message;
bool done = false;
Todo(this.message);
}
@Mirrored()
void addTodo(List<Todo> todos, String message) {
todos.add(Todo(message));
}
3. Generate the code
Run the build runner to generate the static reflection data.
dart run build_runner build
4. Use Reflection
In your main.dart file, add the @entrypoint annotation and import the generated file. The .mirror.dart file will be generated in the same location as your main.dart.
import 'package:mirror/mirror.dart';
import 'main.mirror.dart'; // Import the generated code
// Mark this as the entry point for mirror generation
@entrypoint
void main() {
// 1. Initialize the generated mirrors
initializeMirrors();
// 2. Reflect on a class definition
final todoClass = reflectClass(Todo);
// 3. Create an instance dynamically
final todoInstance = todoClass.newInstance<Todo>('new', ['Learn mirrors']);
// 4. Invoke getters, setters, or methods
print('Created todo: ${todoInstance.invokeGetter('message')}');
// 5. Inspect global functions
final addFunc = functions.firstWhere((element) => element.name == 'addTodo');
print('Found function: ${addFunc.name}');
}