platform/packages/reflection/README.md

194 lines
4.8 KiB
Markdown
Raw Normal View History

# Platform Reflection
2024-11-28 23:13:19 +00:00
A lightweight, cross-platform reflection system for Dart that provides runtime type introspection and manipulation with an API similar to `dart:mirrors` but without its limitations.
2024-11-28 23:13:19 +00:00
## Features
- ✅ Works on all platforms (Web, Mobile, Desktop)
- ✅ No dependency on `dart:mirrors`
- ✅ Pure runtime reflection
- ✅ No code generation required
- ✅ No manual registration needed
- ✅ Complete mirror-based API
2024-11-28 23:13:19 +00:00
- ✅ Type-safe property access
- ✅ Method invocation with argument validation
- ✅ Constructor invocation support
- ✅ Library and isolate reflection
- ✅ Full MirrorSystem implementation
2024-11-28 23:13:19 +00:00
- ✅ Comprehensive error handling
## Installation
Add this to your package's `pubspec.yaml` file:
```yaml
dependencies:
platform_reflection: ^0.1.0
2024-11-28 23:13:19 +00:00
```
## Usage
### Basic Reflection
2024-11-28 23:13:19 +00:00
Simply mark your class with `@reflectable`:
2024-11-28 23:13:19 +00:00
```dart
import 'package:platform_reflection/reflection.dart';
2024-11-28 23:13:19 +00:00
@reflectable
class User {
2024-11-28 23:13:19 +00:00
String name;
int age;
final String id;
User(this.name, this.age, {required this.id});
void birthday() {
age++;
}
String greet(String greeting) {
return '$greeting, $name!';
}
2024-11-28 23:13:19 +00:00
}
```
Then use reflection directly:
2024-11-28 23:13:19 +00:00
```dart
// Get the reflector instance
final reflector = RuntimeReflector.instance;
2024-11-28 23:13:19 +00:00
// Create instance using reflection
final user = reflector.createInstance(
2024-11-28 23:13:19 +00:00
User,
positionalArgs: ['John', 30],
namedArgs: {'id': '123'},
) as User;
2024-11-28 23:13:19 +00:00
// Get instance mirror
final mirror = reflector.reflect(user);
2024-11-28 23:13:19 +00:00
// Access properties
print(mirror.getField(const Symbol('name')).reflectee); // John
print(mirror.getField(const Symbol('age')).reflectee); // 30
2024-11-28 23:13:19 +00:00
// Modify properties
mirror.setField(const Symbol('name'), 'Jane');
mirror.setField(const Symbol('age'), 25);
// Invoke methods
mirror.invoke(const Symbol('birthday'), []);
final greeting = mirror.invoke(const Symbol('greet'), ['Hello']).reflectee;
print(greeting); // Hello, Jane!
2024-11-28 23:13:19 +00:00
```
### Type Information
2024-11-28 23:13:19 +00:00
```dart
// Get mirror system
final mirrors = reflector.currentMirrorSystem;
2024-11-28 23:13:19 +00:00
// Get type mirror
final typeMirror = mirrors.reflectType(User);
2024-11-28 23:13:19 +00:00
// Access type information
print(typeMirror.name); // User
print(typeMirror.properties); // {name: PropertyMetadata(...), age: PropertyMetadata(...)}
print(typeMirror.methods); // {birthday: MethodMetadata(...), greet: MethodMetadata(...)}
2024-11-28 23:13:19 +00:00
// Check type relationships
if (typeMirror.isSubtypeOf(otherType)) {
print('User is a subtype');
}
// Get declarations
final declarations = typeMirror.declarations;
for (var member in declarations.values) {
if (member is MethodMirror) {
print('Method: ${member.simpleName}');
} else if (member is VariableMirror) {
print('Variable: ${member.simpleName}');
}
}
// Access special types
print(mirrors.dynamicType.name); // dynamic
print(mirrors.voidType.name); // void
print(mirrors.neverType.name); // Never
2024-11-28 23:13:19 +00:00
```
### Library Reflection
2024-11-28 23:13:19 +00:00
```dart
// Get a library
final library = mirrors.findLibrary(const Symbol('package:myapp/src/models.dart'));
2024-11-28 23:13:19 +00:00
// Access library members
final declarations = library.declarations;
for (var decl in declarations.values) {
print('Declaration: ${decl.simpleName}');
}
// Check imports
for (var dep in library.libraryDependencies) {
if (dep.isImport) {
print('Imports: ${dep.targetLibrary?.uri}');
}
}
```
### Isolate Reflection
```dart
// Get current isolate
final currentIsolate = mirrors.isolate;
print('Current isolate: ${currentIsolate.debugName}');
// Reflect on another isolate
final isolate = await Isolate.spawn(workerFunction, message);
final isolateMirror = reflector.reflectIsolate(isolate, 'worker');
// Control isolate
await isolateMirror.pause();
await isolateMirror.resume();
await isolateMirror.kill();
2024-11-28 23:13:19 +00:00
```
## Error Handling
The package provides specific exceptions for different error cases:
- `NotReflectableException`: Thrown when attempting to reflect on a non-reflectable type
- `ReflectionException`: Base class for reflection-related errors
- `InvalidArgumentsException`: Thrown when providing invalid arguments to a method or constructor
- `MemberNotFoundException`: Thrown when a property or method is not found
```dart
try {
reflect(NonReflectableClass());
2024-11-28 23:13:19 +00:00
} catch (e) {
print(e); // NotReflectableException: Type NonReflectableClass is not reflectable
2024-11-28 23:13:19 +00:00
}
```
## Design Philosophy
This package provides a reflection API that closely mirrors the design of `dart:mirrors` while being:
2024-11-28 23:13:19 +00:00
- Platform independent
- Lightweight
- Type-safe
- Performant
- Easy to use
2024-11-28 23:13:19 +00:00
The implementation uses pure Dart runtime scanning to provide reflection capabilities across all platforms without requiring code generation or manual registration.
2024-11-28 23:13:19 +00:00
## Contributing
Contributions are welcome! Please read our [contributing guidelines](CONTRIBUTING.md) before submitting pull requests.
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.