2024-12-25 21:31:41 +00:00
|
|
|
import 'package:platform_mirrors/mirrors.dart';
|
2024-12-16 01:34:28 +00:00
|
|
|
|
|
|
|
// Custom annotation to demonstrate metadata
|
|
|
|
class Validate {
|
|
|
|
final String pattern;
|
|
|
|
const Validate(this.pattern);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Interface to demonstrate reflection with interfaces
|
|
|
|
@reflectable
|
|
|
|
abstract class Identifiable {
|
|
|
|
String get id;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Base class to demonstrate inheritance
|
|
|
|
@reflectable
|
|
|
|
abstract class Entity implements Identifiable {
|
|
|
|
final String _id;
|
|
|
|
|
|
|
|
Entity(this._id);
|
|
|
|
|
|
|
|
@override
|
|
|
|
String get id => _id;
|
|
|
|
|
|
|
|
@override
|
|
|
|
String toString() => 'Entity($_id)';
|
|
|
|
}
|
|
|
|
|
|
|
|
// Generic class to demonstrate type parameters
|
|
|
|
@reflectable
|
|
|
|
class Container<T> {
|
|
|
|
final T value;
|
|
|
|
|
|
|
|
Container(this.value);
|
|
|
|
|
|
|
|
T getValue() => value;
|
|
|
|
}
|
|
|
|
|
|
|
|
@reflectable
|
|
|
|
class User extends Entity {
|
|
|
|
@Validate(r'^[a-zA-Z\s]+$')
|
|
|
|
String name;
|
|
|
|
|
|
|
|
int age;
|
|
|
|
|
|
|
|
final List<String> tags;
|
|
|
|
|
|
|
|
User(String id, this.name, this.age, [this.tags = const []]) : super(id) {
|
|
|
|
_userCount++;
|
|
|
|
}
|
|
|
|
|
|
|
|
User.guest() : this('guest', 'Guest User', 0);
|
|
|
|
|
|
|
|
static int _userCount = 0;
|
|
|
|
static int get userCount => _userCount;
|
|
|
|
|
|
|
|
String greet([String greeting = 'Hello']) {
|
|
|
|
return '$greeting $name!';
|
|
|
|
}
|
|
|
|
|
|
|
|
void addTag(String tag) {
|
|
|
|
if (!tags.contains(tag)) {
|
|
|
|
tags.add(tag);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
String getName() => name;
|
|
|
|
|
|
|
|
@override
|
|
|
|
String toString() =>
|
|
|
|
'User($id, $name, age: $age)${tags.isNotEmpty ? " [${tags.join(", ")}]" : ""}';
|
|
|
|
}
|
|
|
|
|
|
|
|
void main() async {
|
|
|
|
// Register classes for reflection
|
2024-12-25 21:31:41 +00:00
|
|
|
ReflectionRegistry.register(Identifiable);
|
|
|
|
ReflectionRegistry.register(Entity);
|
|
|
|
ReflectionRegistry.register(User);
|
|
|
|
ReflectionRegistry.register(Container);
|
2024-12-16 01:34:28 +00:00
|
|
|
|
|
|
|
// Register Container<int> specifically for reflection
|
|
|
|
final container = Container<int>(42);
|
2024-12-25 21:31:41 +00:00
|
|
|
ReflectionRegistry.register(container.runtimeType);
|
2024-12-16 01:34:28 +00:00
|
|
|
|
|
|
|
// Register property metadata directly
|
2024-12-25 21:31:41 +00:00
|
|
|
ReflectionRegistry.registerPropertyMetadata(
|
2024-12-16 01:34:28 +00:00
|
|
|
User,
|
|
|
|
'name',
|
|
|
|
PropertyMetadata(
|
|
|
|
name: 'name',
|
|
|
|
type: String,
|
|
|
|
isReadable: true,
|
|
|
|
isWritable: true,
|
|
|
|
attributes: [Validate(r'^[a-zA-Z\s]+$')],
|
|
|
|
),
|
|
|
|
);
|
|
|
|
|
2024-12-25 21:31:41 +00:00
|
|
|
ReflectionRegistry.registerPropertyMetadata(
|
2024-12-16 01:34:28 +00:00
|
|
|
User,
|
|
|
|
'age',
|
|
|
|
PropertyMetadata(
|
|
|
|
name: 'age',
|
|
|
|
type: int,
|
|
|
|
isReadable: true,
|
|
|
|
isWritable: true,
|
|
|
|
),
|
|
|
|
);
|
|
|
|
|
2024-12-25 21:31:41 +00:00
|
|
|
ReflectionRegistry.registerPropertyMetadata(
|
2024-12-16 01:34:28 +00:00
|
|
|
User,
|
|
|
|
'tags',
|
|
|
|
PropertyMetadata(
|
|
|
|
name: 'tags',
|
|
|
|
type: List,
|
|
|
|
isReadable: true,
|
|
|
|
isWritable: false,
|
|
|
|
),
|
|
|
|
);
|
|
|
|
|
2024-12-25 21:31:41 +00:00
|
|
|
ReflectionRegistry.registerPropertyMetadata(
|
2024-12-16 01:34:28 +00:00
|
|
|
User,
|
|
|
|
'id',
|
|
|
|
PropertyMetadata(
|
|
|
|
name: 'id',
|
|
|
|
type: String,
|
|
|
|
isReadable: true,
|
|
|
|
isWritable: false,
|
|
|
|
),
|
|
|
|
);
|
|
|
|
|
|
|
|
// Register User methods
|
2024-12-25 21:31:41 +00:00
|
|
|
ReflectionRegistry.registerMethod(
|
2024-12-16 01:34:28 +00:00
|
|
|
User,
|
|
|
|
'greet',
|
|
|
|
[String],
|
|
|
|
false,
|
|
|
|
parameterNames: ['greeting'],
|
|
|
|
isRequired: [false],
|
|
|
|
);
|
|
|
|
|
2024-12-25 21:31:41 +00:00
|
|
|
ReflectionRegistry.registerMethod(
|
2024-12-16 01:34:28 +00:00
|
|
|
User,
|
|
|
|
'addTag',
|
|
|
|
[String],
|
|
|
|
true,
|
|
|
|
parameterNames: ['tag'],
|
|
|
|
isRequired: [true],
|
|
|
|
);
|
|
|
|
|
2024-12-25 21:31:41 +00:00
|
|
|
ReflectionRegistry.registerMethod(
|
2024-12-16 01:34:28 +00:00
|
|
|
User,
|
|
|
|
'getName',
|
|
|
|
[],
|
|
|
|
false,
|
|
|
|
);
|
|
|
|
|
|
|
|
// Register constructors with creators
|
2024-12-25 21:31:41 +00:00
|
|
|
ReflectionRegistry.registerConstructor(
|
2024-12-16 01:34:28 +00:00
|
|
|
User,
|
|
|
|
'',
|
|
|
|
parameterTypes: [String, String, int, List],
|
|
|
|
parameterNames: ['id', 'name', 'age', 'tags'],
|
|
|
|
isRequired: [true, true, true, false],
|
|
|
|
creator: (id, name, age, [tags]) => User(
|
|
|
|
id as String,
|
|
|
|
name as String,
|
|
|
|
age as int,
|
|
|
|
tags as List<String>? ?? const [],
|
|
|
|
),
|
|
|
|
);
|
|
|
|
|
2024-12-25 21:31:41 +00:00
|
|
|
ReflectionRegistry.registerConstructor(
|
2024-12-16 01:34:28 +00:00
|
|
|
User,
|
|
|
|
'guest',
|
|
|
|
creator: () => User.guest(),
|
|
|
|
);
|
|
|
|
|
|
|
|
// Create reflector instance
|
|
|
|
final reflector = RuntimeReflector.instance;
|
|
|
|
|
|
|
|
// Demonstrate generic type reflection
|
|
|
|
print('Container value: ${container.getValue()}');
|
|
|
|
|
|
|
|
try {
|
|
|
|
// Create User instance using reflection
|
|
|
|
final user = reflector.createInstance(
|
|
|
|
User,
|
|
|
|
positionalArgs: [
|
|
|
|
'user1',
|
|
|
|
'John Doe',
|
|
|
|
30,
|
|
|
|
['admin', 'user']
|
|
|
|
],
|
|
|
|
) as User;
|
|
|
|
|
|
|
|
print('\nCreated user: $user');
|
|
|
|
|
|
|
|
// Create guest user using named constructor
|
|
|
|
final guest = reflector.createInstance(
|
|
|
|
User,
|
|
|
|
constructorName: 'guest',
|
|
|
|
) as User;
|
|
|
|
|
|
|
|
print('Created guest: $guest');
|
|
|
|
|
|
|
|
// Demonstrate property reflection
|
|
|
|
final userMirror = reflector.reflect(user);
|
|
|
|
|
|
|
|
// Get property values
|
|
|
|
print('\nProperty values:');
|
|
|
|
print('ID: ${userMirror.getField(const Symbol('id')).reflectee}');
|
|
|
|
print('Name: ${userMirror.getField(const Symbol('name')).reflectee}');
|
|
|
|
print('Age: ${userMirror.getField(const Symbol('age')).reflectee}');
|
|
|
|
print('Tags: ${userMirror.getField(const Symbol('tags')).reflectee}');
|
|
|
|
|
|
|
|
// Try to modify properties
|
|
|
|
userMirror.setField(const Symbol('name'), 'Jane Doe');
|
|
|
|
userMirror.setField(const Symbol('age'), 25);
|
|
|
|
print('\nAfter property changes: $user');
|
|
|
|
|
|
|
|
// Try to modify read-only property (should throw)
|
|
|
|
try {
|
|
|
|
userMirror.setField(const Symbol('id'), 'new_id');
|
|
|
|
print('ERROR: Should not be able to modify read-only property');
|
|
|
|
} catch (e) {
|
|
|
|
print('\nExpected error when modifying read-only property id: $e');
|
|
|
|
}
|
|
|
|
|
|
|
|
// Invoke methods
|
|
|
|
final greeting = userMirror.invoke(const Symbol('greet'), ['Hi']).reflectee;
|
|
|
|
print('\nGreeting: $greeting');
|
|
|
|
|
|
|
|
userMirror.invoke(const Symbol('addTag'), ['vip']);
|
|
|
|
print('After adding tag: $user');
|
|
|
|
|
|
|
|
final name = userMirror.invoke(const Symbol('getName'), []).reflectee;
|
|
|
|
print('Got name: $name');
|
|
|
|
|
|
|
|
// Demonstrate type metadata and relationships
|
|
|
|
final userType = reflector.reflectType(User);
|
|
|
|
print('\nType information:');
|
|
|
|
print('Type name: ${userType.name}');
|
|
|
|
|
|
|
|
// Show available properties
|
|
|
|
final properties = (userType as dynamic).properties;
|
|
|
|
print('\nDeclared properties:');
|
|
|
|
properties.forEach((name, metadata) {
|
|
|
|
print(
|
|
|
|
'- $name: ${metadata.type}${metadata.isWritable ? "" : " (read-only)"}');
|
|
|
|
if (metadata.attributes.isNotEmpty) {
|
|
|
|
metadata.attributes.forEach((attr) {
|
|
|
|
if (attr is Validate) {
|
|
|
|
print(' @Validate(${attr.pattern})');
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// Show available methods
|
|
|
|
final methods = (userType as dynamic).methods;
|
|
|
|
print('\nDeclared methods:');
|
|
|
|
methods.forEach((name, metadata) {
|
|
|
|
print('- $name');
|
|
|
|
});
|
|
|
|
|
|
|
|
// Show constructors
|
|
|
|
final constructors = (userType as dynamic).constructors;
|
|
|
|
print('\nDeclared constructors:');
|
|
|
|
constructors.forEach((metadata) {
|
|
|
|
print('- ${metadata.name}');
|
|
|
|
});
|
|
|
|
|
|
|
|
// Demonstrate type relationships
|
|
|
|
final identifiableType = reflector.reflectType(Identifiable);
|
|
|
|
print('\nType relationships:');
|
|
|
|
print(
|
|
|
|
'User is assignable to Identifiable: ${userType.isAssignableTo(identifiableType)}');
|
|
|
|
print(
|
|
|
|
'User is subtype of Entity: ${userType.isSubtypeOf(reflector.reflectType(Entity))}');
|
|
|
|
} catch (e) {
|
|
|
|
print('Error: $e');
|
|
|
|
print(e.runtimeType);
|
|
|
|
}
|
|
|
|
}
|