platform/packages/reflection
2024-11-21 20:04:34 -07:00
..
example add: adding reflection package 2024-11-21 20:04:34 -07:00
lib add: adding reflection package 2024-11-21 20:04:34 -07:00
test add: adding reflection package 2024-11-21 20:04:34 -07:00
LICENSE add: adding reflection package 2024-11-21 20:04:34 -07:00
pubspec.lock add: adding reflection package 2024-11-21 20:04:34 -07:00
pubspec.yaml add: adding reflection package 2024-11-21 20:04:34 -07:00
README.md add: adding reflection package 2024-11-21 20:04:34 -07:00

Dart Pure Reflection

A lightweight, cross-platform reflection system for Dart that provides runtime type introspection and manipulation without using dart:mirrors or code generation.

Features

  • Works on all platforms (Web, Mobile, Desktop)
  • No dependency on dart:mirrors
  • No code generation required
  • Pure runtime reflection
  • Type-safe property access
  • Method invocation with argument validation
  • Constructor invocation support
  • Comprehensive error handling

Installation

Add this to your package's pubspec.yaml file:

dependencies:
  reflection: ^1.0.0

Usage

Basic Setup

  1. Add the @reflectable annotation and Reflector mixin to your class:
import 'package:reflection/reflection.dart';

@reflectable
class User with Reflector {
  String name;
  int age;
  final String id;

  User(this.name, this.age, {required this.id});
}
  1. Register your class and its constructors:
// Register the class
Reflector.register(User);

// Register constructors
Reflector.registerConstructor(
  User,
  '', // Default constructor
  (String name, int age, {String? id}) {
    if (id == null) throw ArgumentError.notNull('id');
    return User(name, age, id: id);
  },
);

Reflecting on Types

final reflector = RuntimeReflector.instance;

// Get type metadata
final userType = reflector.reflectType(User);
print('Type name: ${userType.name}');
print('Properties: ${userType.properties.keys.join(', ')}');
print('Methods: ${userType.methods.keys.join(', ')}');

Working with Instances

final user = User('john_doe', 30, id: 'usr_123');
final userReflector = reflector.reflect(user);

// Read properties
final name = userReflector.getField('name'); // john_doe
final age = userReflector.getField('age');   // 30

// Write properties
userReflector.setField('name', 'jane_doe');
userReflector.setField('age', 25);

// Invoke methods
userReflector.invoke('someMethod', ['arg1', 'arg2']);

Creating Instances

// Using default constructor
final newUser = reflector.createInstance(
  User,
  positionalArgs: ['alice', 28],
  namedArgs: {'id': 'usr_456'},
) as User;

// Using named constructor
final specialUser = reflector.createInstance(
  User,
  constructorName: 'special',
  positionalArgs: ['bob'],
) as User;

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
try {
  reflector.reflect(NonReflectableClass());
} catch (e) {
  print(e); // NotReflectableException: Type "NonReflectableClass" is not marked as @reflectable
}

Complete Example

See the example for a complete working demonstration.

Limitations

  1. Type Discovery

    • Properties and methods must be registered explicitly
    • No automatic discovery of class members
    • Generic type information is limited
  2. Performance

    • First access to a type involves metadata creation
    • Subsequent accesses use cached metadata
  3. Private Members

    • Private fields and methods cannot be accessed
    • Reflection is limited to public API

Design Philosophy

This package is inspired by:

  • dart:mirrors: API design and metadata structure
  • fake_reflection: Registration-based approach
  • mirrors.cc: Runtime type handling

The goal is to provide a lightweight, cross-platform reflection system that:

  • Works everywhere Dart runs
  • Requires minimal setup
  • Provides type-safe operations
  • Maintains good performance
  • Follows Dart best practices

Contributing

Contributions are welcome! Please read our contributing guidelines before submitting pull requests.

License

This project is licensed under the MIT License - see the LICENSE file for details.