import 'package:platform_mirrors/mirrors.dart'; // 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 { 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 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 ReflectionRegistry.register(Identifiable); ReflectionRegistry.register(Entity); ReflectionRegistry.register(User); ReflectionRegistry.register(Container); // Register Container specifically for reflection final container = Container(42); ReflectionRegistry.register(container.runtimeType); // Register property metadata directly ReflectionRegistry.registerPropertyMetadata( User, 'name', PropertyMetadata( name: 'name', type: String, isReadable: true, isWritable: true, attributes: [Validate(r'^[a-zA-Z\s]+$')], ), ); ReflectionRegistry.registerPropertyMetadata( User, 'age', PropertyMetadata( name: 'age', type: int, isReadable: true, isWritable: true, ), ); ReflectionRegistry.registerPropertyMetadata( User, 'tags', PropertyMetadata( name: 'tags', type: List, isReadable: true, isWritable: false, ), ); ReflectionRegistry.registerPropertyMetadata( User, 'id', PropertyMetadata( name: 'id', type: String, isReadable: true, isWritable: false, ), ); // Register User methods ReflectionRegistry.registerMethod( User, 'greet', [String], false, parameterNames: ['greeting'], isRequired: [false], ); ReflectionRegistry.registerMethod( User, 'addTag', [String], true, parameterNames: ['tag'], isRequired: [true], ); ReflectionRegistry.registerMethod( User, 'getName', [], false, ); // Register constructors with creators ReflectionRegistry.registerConstructor( 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? ?? const [], ), ); ReflectionRegistry.registerConstructor( 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); } }