platform/incubation/reflection/doc/quick_start.md

369 lines
7.9 KiB
Markdown

# Platform Reflection Quick Start Guide
This guide covers the most common use cases for Platform Reflection to help you get started quickly.
## Installation
```yaml
dependencies:
platform_reflection: ^0.1.0
```
## Basic Usage
### 1. Simple Class Reflection
```dart
import 'package:platform_reflection/reflection.dart';
// 1. Define your class
@reflectable
class User {
String name;
int age;
User(this.name, this.age);
void birthday() => age++;
}
// 2. Register for reflection
void main() {
// Register class
Reflector.register(User);
// Register properties
Reflector.registerProperty(User, 'name', String);
Reflector.registerProperty(User, 'age', int);
// Register methods
Reflector.registerMethod(
User,
'birthday',
[],
true,
);
// Register constructor
Reflector.registerConstructor(
User,
'',
parameterTypes: [String, int],
parameterNames: ['name', 'age'],
creator: (String name, int age) => User(name, age),
);
// Use reflection
final user = reflector.createInstance(
User,
positionalArgs: ['John', 30],
) as User;
final mirror = reflector.reflect(user);
print(mirror.getField(const Symbol('name')).reflectee); // John
mirror.invoke(const Symbol('birthday'), []);
print(mirror.getField(const Symbol('age')).reflectee); // 31
}
```
### 2. Property Access
```dart
// Get property value
final mirror = reflector.reflect(instance);
final name = mirror.getField(const Symbol('name')).reflectee as String;
// Set property value
mirror.setField(const Symbol('name'), 'Jane');
// Check if property exists
final metadata = Reflector.getPropertyMetadata(User);
if (metadata?.containsKey('name') ?? false) {
// Property exists
}
```
### 3. Method Invocation
```dart
// Invoke method without arguments
mirror.invoke(const Symbol('birthday'), []);
// Invoke method with arguments
final result = mirror.invoke(
const Symbol('greet'),
['Hello'],
).reflectee as String;
// Invoke method with named arguments
final result = mirror.invoke(
const Symbol('update'),
[],
{const Symbol('value'): 42},
).reflectee;
```
### 4. Constructor Usage
```dart
// Default constructor
final instance = reflector.createInstance(
User,
positionalArgs: ['John', 30],
) as User;
// Named constructor
final instance = reflector.createInstance(
User,
constructorName: 'guest',
) as User;
// Constructor with named arguments
final instance = reflector.createInstance(
User,
positionalArgs: ['John'],
namedArgs: {const Symbol('age'): 30},
) as User;
```
### 5. Type Information
```dart
// Get type metadata
final metadata = Reflector.getTypeMetadata(User);
// Check properties
for (var property in metadata.properties.values) {
print('${property.name}: ${property.type}');
}
// Check methods
for (var method in metadata.methods.values) {
print('${method.name}(${method.parameterTypes.join(', ')})');
}
```
### 6. Error Handling
```dart
try {
// Attempt reflection
final mirror = reflector.reflect(instance);
mirror.invoke(const Symbol('method'), []);
} on NotReflectableException catch (e) {
print('Type not registered: $e');
} on MemberNotFoundException catch (e) {
print('Member not found: $e');
} on InvalidArgumentsException catch (e) {
print('Invalid arguments: $e');
} on ReflectionException catch (e) {
print('Reflection error: $e');
}
```
## Common Patterns
### 1. Registration Helper
```dart
void registerType<T>(Type type) {
Reflector.register(type);
final scanner = Scanner();
final metadata = scanner.scanType(type);
// Register properties
for (var property in metadata.properties.values) {
Reflector.registerProperty(
type,
property.name,
property.type,
isWritable: property.isWritable,
);
}
// Register methods
for (var method in metadata.methods.values) {
Reflector.registerMethod(
type,
method.name,
method.parameterTypes,
method.returnsVoid,
parameterNames: method.parameters.map((p) => p.name).toList(),
isRequired: method.parameters.map((p) => p.isRequired).toList(),
);
}
}
```
### 2. Property Observer
```dart
class PropertyObserver {
final InstanceMirror mirror;
final Symbol propertyName;
final void Function(dynamic oldValue, dynamic newValue) onChange;
PropertyObserver(this.mirror, this.propertyName, this.onChange);
void observe() {
var lastValue = mirror.getField(propertyName).reflectee;
Timer.periodic(Duration(milliseconds: 100), (_) {
final currentValue = mirror.getField(propertyName).reflectee;
if (currentValue != lastValue) {
onChange(lastValue, currentValue);
lastValue = currentValue;
}
});
}
}
```
### 3. Method Interceptor
```dart
class MethodInterceptor {
final InstanceMirror mirror;
final Symbol methodName;
final void Function(List args, Map<Symbol, dynamic> named) beforeInvoke;
final void Function(dynamic result) afterInvoke;
MethodInterceptor(
this.mirror,
this.methodName,
{this.beforeInvoke = _noOp,
this.afterInvoke = _noOp});
static void _noOp([dynamic _]) {}
dynamic invoke(List args, [Map<Symbol, dynamic>? named]) {
beforeInvoke(args, named ?? {});
final result = mirror.invoke(methodName, args, named).reflectee;
afterInvoke(result);
return result;
}
}
```
## Best Practices
1. **Register Early**
```dart
void main() {
// Register all types at startup
registerType<User>();
registerType<Order>();
registerType<Product>();
// Start application
runApp();
}
```
2. **Cache Mirrors**
```dart
class UserService {
final Map<User, InstanceMirror> _mirrors = {};
InstanceMirror getMirror(User user) {
return _mirrors.putIfAbsent(
user,
() => reflector.reflect(user),
);
}
}
```
3. **Handle Errors**
```dart
T reflectSafely<T>(Function() operation, T defaultValue) {
try {
return operation() as T;
} on ReflectionException catch (e) {
print('Reflection failed: $e');
return defaultValue;
}
}
```
4. **Validate Registration**
```dart
bool isFullyRegistered(Type type) {
final metadata = Reflector.getTypeMetadata(type);
if (metadata == null) return false;
// Check properties
if (metadata.properties.isEmpty) return false;
// Check methods
if (metadata.methods.isEmpty) return false;
// Check constructors
if (metadata.constructors.isEmpty) return false;
return true;
}
```
## Common Issues
1. **Type Not Registered**
```dart
// Wrong
reflector.reflect(unregisteredInstance);
// Right
Reflector.register(UnregisteredType);
reflector.reflect(instance);
```
2. **Missing Property/Method Registration**
```dart
// Wrong
Reflector.register(User);
// Right
Reflector.register(User);
Reflector.registerProperty(User, 'name', String);
Reflector.registerMethod(User, 'greet', [String]);
```
3. **Wrong Argument Types**
```dart
// Wrong
mirror.invoke(const Symbol('greet'), [42]);
// Right
mirror.invoke(const Symbol('greet'), ['Hello']);
```
## Performance Tips
1. **Cache Metadata**
```dart
final metadata = Reflector.getTypeMetadata(User);
final properties = metadata.properties;
final methods = metadata.methods;
```
2. **Reuse Mirrors**
```dart
final mirror = reflector.reflect(instance);
// Reuse mirror for multiple operations
```
3. **Batch Registration**
```dart
void registerAll() {
for (var type in types) {
registerType(type);
}
}
```
## Next Steps
- Read the [Technical Specification](technical_specification.md) for detailed implementation information
- Check the [API Reference](../README.md#api-reference) for complete API documentation
- See the [Mirrors Comparison](mirrors_comparison.md) for differences from dart:mirrors