Reflection
XXML's reflection system allows runtime introspection of types, enabling frameworks for serialization, validation, and dependency injection.
Import
xxml
#import Language::Reflection;Type Class
The Type class provides access to type metadata:
xxml
// Get type information by name
Instantiate Type^ As <type> = Type::forName(String::Constructor("MyClass"));
// Get type name
Instantiate String^ As <name> = type.getName();
// Check if class is final
Instantiate Bool^ As <isFinal> = type.isFinal();
// Get base class name
Instantiate String^ As <base> = type.getBaseClassName();Property Introspection
xxml
// Get property count
Instantiate Integer^ As <count> = type.getPropertyCount();
// Iterate over properties
For (Integer <i> = 0 .. count) -> {
Instantiate PropertyInfo^ As <prop> = type.getPropertyAt(i);
Instantiate String^ As <propName> = prop.getName();
Instantiate String^ As <propType> = prop.getTypeName();
Instantiate String^ As <ownership> = prop.getOwnership();
Run Console::printLine(propName);
}Method Introspection
xxml
// Get method count
Instantiate Integer^ As <methodCount> = type.getMethodCount();
// Get method by name
Instantiate MethodInfo^ As <method> = type.getMethodByName(String::Constructor("doSomething"));
// Get method details
Instantiate String^ As <returnType> = method.getReturnTypeName();
Instantiate Integer^ As <paramCount> = method.getParameterCount();Annotation Access
Access annotations that were marked with Retain:
xxml
// Check annotation count
Instantiate Integer^ As <annotCount> = type.getAnnotationCount();
// Get annotation by index
Instantiate AnnotationInfo^ As <annot> = type.getAnnotationAt(Integer::Constructor(0));
// Get annotation name
Instantiate String^ As <annotName> = annot.getName();
// Get annotation arguments
Instantiate AnnotationArg^ As <arg> = annot.getArgumentByName(String::Constructor("value"));
Instantiate String^ As <argValue> = arg.asString();Note
Only annotations declared with the
Retain keyword are available at runtime. Compile-time-only annotations are discarded after processing.Complete Example
reflection-example.xxml
#import Language::Core;
#import Language::Reflection;
[ Annotation <Entity> Allows (AnnotationAllow::Classes) Retain
Annotate (String^)(tableName);
]
@Entity(tableName = "users")
[ Class <User> Final Extends None
[ Public <>
Property <id> Types Integer^;
Property <name> Types String^;
Constructor = default;
]
]
[ Entrypoint
{
// Get type info
Instantiate Type^ As <type> = Type::forName(String::Constructor("User"));
// Read annotation
Instantiate AnnotationInfo^ As <entity> = type.getAnnotationAt(Integer::Constructor(0));
Instantiate AnnotationArg^ As <tableArg> = entity.getArgumentByName(String::Constructor("tableName"));
Run Console::printLine(String::Constructor("Table: ").append(tableArg.asString()));
// Output: Table: users
// List properties
Instantiate Integer^ As <propCount> = type.getPropertyCount();
For (Integer <i> = 0 .. propCount) -> {
Instantiate PropertyInfo^ As <prop> = type.getPropertyAt(i);
Run Console::printLine(prop.getName());
}
// Output: id, name
Exit(0);
}
]Use Cases
- Serialization: Automatically convert objects to JSON/XML based on their structure
- Validation: Read validation annotations and verify property values
- Dependency Injection: Automatically wire dependencies based on annotations
- ORM: Map classes to database tables using reflection
Next Steps
Learn about Annotations to define custom metadata for your classes.