Reflective programming: Difference between revisions

Content deleted Content added
 
(15 intermediate revisions by the same user not shown)
Line 76:
using std::meta::info;
using std::views::filter;
 
class Foo {
private:
// ...
public:
void printHello() const noexcept {
std::println("Hello, world!");
}
};
 
[[nodiscard]]
Line 96 ⟶ 105:
 
template <info Ty, auto Name>
constexpr auto createInvokerImpl = []() -> auto {
using Type = [: Ty :];
static constexpr info M = findMethod(Ty, Name);
static_assert(parameters_of(M).size() == 0 && return_type_of(M) == ^^void);
return [](Type& instance) -> void { instance.[: M :](); };
}();
 
Line 128 ⟶ 137:
 
<syntaxhighlight lang="c#">
using System;
// Without reflection
using System.Reflection;
Foo foo = new Foo();
foo.PrintHello();
 
class Foo {
// With reflection
// ...
Object foo = Activator.CreateInstance("complete.classpath.and.Foo");
public void PrintHello() {
MethodInfo method = foo.GetType().GetMethod("PrintHello");
Console.WriteLine("Hello, world!");
method.Invoke(foo, null);
}
}
 
public class InvokeFooExample {
static void Main(string[] args) {
// Without reflection
Foo foo = new Foo();
foo.PrintHello();
 
// With reflection
Object foo = Activator.CreateInstance("complete.classpath.and.Foo");
MethodInfo method = foo.GetType().GetMethod("PrintHello");
method.Invoke(foo, null);
}
}
</syntaxhighlight>
 
Line 211 ⟶ 234:
<syntaxhighlight lang="java">
import java.lang.reflect.Method;
 
class Foo {
// ...
public void printHello() {
System.out.println("Hello, world!");
}
}
 
public class InvokeFooExample {
public static void main(String[] args) {
// Without reflection
Foo foo = new Foo();// Without reflection
Foo foo.hello = new Foo();
foo.printHello();
 
// With reflection
try {
Foo foo = Foo.class.getDeclaredConstructor().newInstance();
 
Method m = foo.getClass().getDeclaredMethod("helloprintHello", new Class<?>[0]);
m.invoke(foo);
} catch (ReflectiveOperationException e) {
System.err.printf("An error occurred: %s%n", e.getMessage());
}
}
}
Line 294 ⟶ 326:
 
// Sending "hello" to a Foo instance without reflection.
Foo * obj = [[Foo alloc] init];
[obj hello];
 
Line 347 ⟶ 379:
 
<syntaxhighlight lang="python">
from typing import Any
# Without reflection
obj = Foo()
obj.hello()
 
class Foo:
# With reflection
# ...
obj = globals()["Foo"]()
def print_hello() -> None:
getattr(obj, "hello")()
print("Hello, world!")
 
if __name__ == "__main__":
# With eval
# Without reflection
eval("Foo().hello()")
obj: Foo = Foo()
obj.print_hello()
 
# With reflection
obj: Foo = globals()["Foo"]()
_: Any = getattr(obj, "print_hello")()
 
# With eval
eval("Foo().print_hello()")
</syntaxhighlight>
 
Line 388 ⟶ 428:
# With eval
eval "Foo.new.hello"
</syntaxhighlight>
 
===Rust===
[[Rust (programming language)|Rust]] does not have compile-time reflection in the standard library, but it is possible using some third-party libraries such as "[https://docs.rs/bevy_reflect/latest/bevy_reflect/ {{mono|bevy_reflect}}]".
 
<syntaxhighlight lang="rust">
use std::any::TypeId;
 
use bevy_reflect::prelude::*;
use bevy_reflect::{
FunctionRegistry,
GetTypeRegistration,
Reflect,
ReflectFunction,
ReflectFunctionRegistry,
ReflectMut,
ReflectRef,
TypeRegistry
};
 
#[derive(Reflect)]
#[reflect(DoFoo)]
struct Foo {
// ...
}
 
impl Foo {
fn new() -> Self {
Foo {}
}
 
fn print_hello(&self) {
println!("Hello, world!");
}
}
 
#[reflect_trait]
trait DoFoo {
fn print_hello(&self);
}
 
impl DoFoo for Foo {
fn print_hello(&self) {
self.print_hello();
}
}
 
fn main() {
// Without reflection
let foo: Foo = Foo::new();
foo.print_hello();
 
// With reflection
let mut registry: TypeRegistry = TypeRegistry::default();
 
registry.register::<Foo>();
registry.register_type_data::<Foo, ReflectFunctionRegistry>();
registry.register_type_data::<Foo, ReflectDoFoo>();
 
let foo: Foo = Foo;
let reflect_foo: Box<dyn Reflect> = Box::new(foo);
 
// Version 1: call hello by trait
let trait_registration: &ReflectDoFoo = registry
.get_type_data::<ReflectDoFoo>(TypeId::of::<Foo>())
.expect("ReflectDoFoo not found for Foo");
 
let trait_object: &dyn DoFoo = trait_registration
.get(&*reflect_foo)
.expect("Failed to get DoFoo trait object");
 
trait_object.print_hello();
 
// Version 2: call hello by function name
let func_registry: &FunctionRegistry = registry
.get_type_data::<FunctionRegistry>(TypeId::of::<Foo>())
.expect("FunctionRegistry not found for Foo");
 
if let Some(dyn_func) = func_registry.get("print_hello") {
let result: Option<Box<dyn Reflect>> = dyn_func
.call(&*reflect_foo, Vec::<Box<dyn Reflect>>::new())
.ok();
 
if result.is_none() {
println!("Function called, no result returned (as expected for void return)");
}
} else {
println!("No function named hello found in FunctionRegistry");
}
}
</syntaxhighlight>