mc::reflect 反射模块
概述
反射模块为 C++ 类型提供编译期静态反射能力,支持结构体/类属性访问、方法调用、枚举值与名称互转,以及运行时动态对象创建和类型注册。
主要特性
- 编译期宏驱动:通过
MC_REFLECTABLE、MC_REFLECT、MC_REFLECT_ENUM等宏声明反射元数据,零运行时开销 - 属性访问:支持成员变量、计算属性(getter/setter),通过名称或偏移量读写属性值
- 方法调用:支持反射成员函数和静态函数,可同步/异步调用,参数通过 variants 传递
- serialization:通过
to_variant/from_variant在任意可反射类型与 variant/dict 之间互转 - 枚举反射:枚举值与字符串名称双向查找,支持
try_get_value/try_get_name安全查询 - 类型注册与工厂:
reflection_factory管理全局类型注册表,支持按 type_id 或名称动态创建对象 - 命名空间隔离:
MC_REFLECT_WITH_NAMESPACE/MC_REFLECT_ENUM_WITH_NAMESPACE将类型注册到独立命名空间工厂 - 基类支持:
MC_BASE_CLASS声明继承关系,可访问基类反射属性和方法 - 运行时元数据:
struct_metadata/enum_metadata提供运行时可查询的类型信息 - 静态元数据:
static_metadata<T>在编译期保存成员的 type_id 和扩展数据
基本用法
示例 1:结构体反射——属性与序列化
#include <mc/reflect.h>
#include <mc/variant.h>
#include <mc/dict.h>
#include <iostream>
struct Person {
MC_REFLECTABLE("Person") // ← 类内声明可反射
std::string name;
int age;
Person() : name(""), age(0) {}
Person(std::string n, int a) : name(std::move(n)), age(a) {}
};
// 在全局作用域定义反射成员
MC_REFLECT(Person, name, age)
int main()
{
Person p("张三", 30);
// to_variant — 将对象序列化为 variant(内部为 dict)
mc::variant v;
mc::reflect::to_variant(p, v);
// v = {"name": "张三", "age": 30}
std::cout << "name: " << v["name"].as<std::string>() << std::endl;
std::cout << "age: " << v["age"].as<int>() << std::endl;
// from_variant — 从 variant 反序列化到对象
mc::dict d{{"name", "李四"}, {"age", 25}};
Person p2;
mc::reflect::from_variant(d, p2);
std::cout << p2.name << " " << p2.age << std::endl; // 李四 25
return 0;
}
示例 2:枚举反射
#include <mc/reflect.h>
#include <mc/variant.h>
#include <iostream>
enum class Color { Red, Green, Blue };
MC_REFLECTABLE("Color", Color) // ← 全局声明(2 个参数)
MC_REFLECT_ENUM(Color,
(Red, "红色"),
(Green, "绿色"),
(Blue, "蓝色"))
int main()
{
// 枚举值 → variant(字符串)
mc::variant v;
mc::reflect::to_variant(Color::Green, v);
std::cout << v.as<std::string>() << std::endl; // "绿色"
// variant → 枚举值
Color c;
mc::reflect::from_variant(mc::variant("蓝色"), c);
// c == Color::Blue
// 通过元数据查询
auto& meta = mc::reflect::reflector<Color>::get_metadata();
std::cout << meta.get_name(1) << std::endl; // "绿色"
std::cout << meta.get_value("红色") << std::endl; // 0
// 安全查询
if (auto v = meta.try_get_value("绿色")) {
std::cout << "value: " << *v << std::endl; // value: 1
}
if (auto n = meta.try_get_name(2)) {
std::cout << "name: " << *n << std::endl; // name: 蓝色
}
return 0;
}
示例 3:反射方法调用与基类访问
#include <mc/reflect.h>
#include <mc/variant.h>
#include <iostream>
struct Animal {
MC_REFLECTABLE("Animal")
virtual std::string speak() const { return "..."; }
int age = 0;
};
struct Dog : Animal {
MC_REFLECTABLE("Dog")
std::string speak() const override { return "Woof!"; }
std::string bark(int times) const {
std::string result;
for (int i = 0; i < times; ++i) result += "Woof! ";
return result;
}
};
MC_REFLECT(Animal, age)
MC_REFLECT(Dog,
bark,
age,
MC_BASE_CLASS(Animal))
int main()
{
Dog dog;
dog.age = 3;
// 反射调用方法
mc::variants args = {5};
mc::variant result = mc::reflect::invoke<Dog>(dog, "bark", args);
std::cout << result.as<std::string>() << std::endl; // Woof! Woof! Woof! Woof! Woof!
// 反射获取属性(包含基类属性)
mc::dict props = mc::reflect::get_all_properties(dog);
for (const auto& kv : props.iter()) {
std::cout << kv->first << " = " << mc::to_string(kv->second) << std::endl;
}
// 输出 age = 3
// 检查方法是否存在
if (mc::reflect::has_method<Dog>("bark")) {
std::cout << "Dog has bark method" << std::endl;
}
// 获取方法参数个数
size_t n = mc::reflect::method_arg_count<Dog>("bark");
std::cout << "bark arg count: " << n << std::endl; // 1
return 0;
}
示例 4:计算属性与类型注册
#include <mc/reflect.h>
#include <mc/variant.h>
#include <mc/dict.h>
#include <iostream>
struct Circle {
MC_REFLECTABLE("Circle")
double radius = 0.0;
double area() const { return 3.14159 * radius * radius; }
double diameter() const { return 2 * radius; }
};
MC_REFLECT(Circle,
radius,
MC_COMPUTED_PROPERTY(Circle, "面积", area),
MC_COMPUTED_PROPERTY(Circle, "直径", diameter))
int main()
{
Circle c{5.0};
// 获取所有属性(含计算属性)
mc::dict props = mc::reflect::get_all_properties(c);
std::cout << mc::to_string(props) << std::endl;
// {"radius": 5.0, "面积": 78.53975, "直径": 10.0}
// 单独获取属性
auto area_v = mc::reflect::get_property(c, "面积");
std::cout << area_v.as<double>() << std::endl; // 78.53975
// 类型注册到全局工厂
mc::reflect::reflector<Circle>::register_type();
// 通过工厂按名称创建对象
auto obj = mc::reflect::create_object("Circle");
std::cout << "type_id: " << obj->get_type_id() << std::endl;
return 0;
}
API 详细说明
头文件
主入口:#include <mc/reflect.h>
入口宏
| 宏 | 作用域 | 说明 |
|---|---|---|
MC_REFLECTABLE(name) |
类内 | 声明该类型可反射,name 为反射类型名。必须是类内第一个宏调用 |
MC_REFLECTABLE("name", TYPE) |
全局 | 声明非类类型(如枚举)可反射,TYPE 为完整类型名 |
MC_REFLECT(TYPE, ...) |
全局 | 定义反射成员。... 为成员名(字段/方法)、MC_BASE_CLASS、MC_COMPUTED_PROPERTY |
MC_REFLECT_ENUM(TYPE, VALUES) |
全局 | 定义枚举反射值。VALUES 格式:(EnumValue, "名称") 或仅 EnumValue |
MC_REFLECT_WITH_NAMESPACE(NS, TYPE, ...) |
全局 | 等同于 MC_REFLECT,但类型注册到命名空间 NS |
MC_REFLECT_ENUM_WITH_NAMESPACE(NS, TYPE, VALUES) |
全局 | 等同于 MC_REFLECT_ENUM,但类型注册到命名空间 NS |
MC_BASE_CLASS(BaseType) |
MC_REFLECT 内 | 声明基类关系(继承 BaseType) |
MC_BASE_CLASS(BaseType, "custom_name") |
MC_REFLECT 内 | 声明基类关系并指定自定义名称 |
MC_COMPUTED_PROPERTY(TYPE, "name", GETTER) |
MC_REFLECT 内 | 定义只读计算属性,GETTER 为成员函数名 |
MC_COMPUTED_PROPERTY(TYPE, "name", GETTER, SETTER) |
MC_REFLECT 内 | 定义可读写计算属性,GETTER/SETTER 为成员函数名 |
MC_MEMBER_OFFSETOF(TYPE, MEMBER) |
全局 | 从数据成员指针取得字节偏移,供自定义 member_info 使用;支持 GCC、Clang 与 MSVC 的成员指针扩展。标准布局类型的具名成员优先使用 MC_OFFSETOF |
mc::reflect::reflector<T>(结构体)
reflector<T> 是静态反射门面,所有方法均为静态。对于非枚举反射类型:
| 方法 | 参数 | 返回值 | 异常 | 线程安全 | 说明 |
|---|---|---|---|---|---|
get_name() |
无 | mc::string_view |
不抛出 | 是 | 返回反射类型名(由 MC_REFLECTABLE 定义) |
get_type_id() |
无 | type_id_type |
不抛出 | 是 | 返回全局唯一类型 ID |
get_extension() |
无 | metadata_extension& |
不抛出 | 是 | 返回扩展数据引用,可存放自定义数据(void* data + 析构函数) |
register_type() |
无 | type_id_type |
可能抛出(注册冲突时) | 是 | 向 reflection_factory 注册此类型,返回 type_id |
unregister_type() |
无 | void |
不抛出 | 是 | 从 reflection_factory 注销此类型 |
to_variant(obj, dict) |
const T&, mc::dict& |
void |
可能抛出(属性值转换时) | 否 | 将对象属性序列化到 dict。若类型定义了静态 to_variant(const T&, mc::dict&) 则优先使用自定义序列化 |
from_variant(dict, obj) |
const mc::dict&, T& |
void |
可能抛出(属性类型不匹配时) | 否 | 从 dict 反序列化到对象。若类型定义了静态 from_variant(const mc::dict&, T&) 则优先使用自定义反序列化 |
get_metadata() |
无 | const struct_metadata& |
不抛出 | 是 | 返回结构体元数据(惰性创建) |
get_reflection() |
无 | reflection<T>& |
不抛出 | 是 | 返回运行时反射单例 |
get_signature(sig) |
mc::string& 或 std::string& |
void |
不抛出 | 是 | 将类型签名写入 sig 字符串 |
visit_properties(visitor) |
property_visitor_t 或可调用对象 |
void |
不抛出 | 否 | 遍历所有属性(含基类),visitor 签名为 visit_status(const property_type_info*) |
visit(visitor) |
void(mc::string_view, getter_t, setter_t) |
void |
不抛出 | 否 | 遍历属性,同时提供名称、getter 和 setter 函数对象 |
mc::reflect::reflector<T>(枚举)
| 方法 | 参数 | 返回值 | 异常 | 线程安全 | 说明 |
|---|---|---|---|---|---|
get_name() |
无 | mc::string_view |
不抛出 | 是 | 返回反射类型名 |
get_type_id() |
无 | type_id_type |
不抛出 | 是 | 返回全局唯一类型 ID |
register_type() |
无 | type_id_type |
可能抛出(注册冲突时) | 是 | 向工厂注册枚举类型 |
unregister_type() |
无 | void |
不抛出 | 是 | 从工厂注销枚举类型 |
to_variant(obj, var) |
const T&, mc::variant& |
void |
可能抛出 bad_enum_cast |
否 | 将枚举值转为 variant 字符串(枚举名) |
from_variant(var, obj) |
const mc::variant&, T& |
void |
可能抛出 bad_enum_cast |
否 | 从 variant 字符串恢复枚举值 |
get_value(obj) |
const T& |
mc::variant |
可能抛出 bad_enum_cast |
否 | 将枚举值转为 variant 字符串(同 to_variant 但返回 variant) |
get_metadata() |
无 | const enum_metadata& |
不抛出 | 是 | 返回枚举元数据 |
get_reflection() |
无 | reflection<T>& |
不抛出 | 是 | 返回运行时反射单例 |
序列化自由函数
// 头文件: <mc/reflect.h>
namespace mc::reflect {
template <typename T>
void to_variant(const T& obj, variant& var);
// 将可反射类型转为 variant。结构体→dict 后装箱为 variant,枚举→字符串 variant。
template <typename T>
void to_variant(const T& obj, mc::dict& dict);
// 将结构体属性写入 dict。枚举类型会将值写入 dict["value"]。
template <typename T>
void from_variant(const variant& var, T& obj);
// 从 variant 反序列化。支持 dict(按属性名匹配)、array(按属性顺序匹配)、字符串(枚举)。
template <typename T, typename Visitor>
void visit_properties(const Visitor& visitor);
} // namespace mc::reflect
| 参数 | 说明 |
|---|---|
obj |
源/目标对象引用 |
var |
source/destination variant |
dict |
destination dict(仅输出) |
visitor |
可调用对象,接收 mc::string_view name, getter_t, setter_t |
全局 ADL 友好版(在 mc 命名空间,通过 SFINAE 仅对可反射类型启用):
template <typename T>
void to_variant(const T& o, variant& v); // SFINAE: is_reflectable<T>
template <typename T>
void from_variant(const variant& v, T& o); // SFINAE: is_reflectable<T>
属性访问自由函数
// 头文件: <mc/reflect/property.h>
namespace mc::reflect {
template <typename T>
mc::variant get_property(const T& obj, mc::string_view key);
// 通过属性名获取属性值。若属性不存在返回空 variant。
template <typename T>
mc::dict get_all_properties(const T& obj);
// 获取对象所有反射属性(含基类),返回 dict。
template <typename T>
bool set_property(T& obj, mc::string_view key, const mc::variant& value);
// 设置属性值,成功返回 true。异常被捕获并返回 false。
template <typename T>
mc::string_view get_property_name(size_t offset);
// 通过成员偏移量反查属性名称。
}
| 参数 | 说明 |
|---|---|
obj |
目标对象引用 |
key |
属性名称(mc::string_view 或 mc::quark) |
value |
要设置的新值 |
offset |
成员在对象内的字节偏移量 |
方法调用自由函数
// 头文件: <mc/reflect/method.h>
namespace mc::reflect {
template <typename T>
mc::variant invoke(T& obj, mc::string_view method_name, const mc::variants& args = {});
// 同步调用反射方法。参数通过 variants 传递,返回值装箱为 variant。
template <typename T>
async_result async_invoke(T& obj, mc::string_view method_name, const mc::variants& args = {});
// 异步调用反射方法。返回 async_result(即 mc::result<mc::variant>)。
template <typename T>
mc::variant invoke(mc::string_view method_name, const mc::variants& args = {});
// 调用静态反射方法(无需对象实例)。
template <typename T>
bool has_method(mc::string_view method_name);
// 检查类型是否具有指定名称的反射方法。
template <typename T>
size_t method_arg_count(mc::string_view method_name);
// 获取指定反射方法的参数个数。不存在时返回 static_cast<size_t>(-1)。
template <typename T>
mc::string_view method_return_type(mc::string_view method_name);
// 获取方法的返回类型签名字符串。
}
| 参数 | 说明 |
|---|---|
obj |
目标对象引用 |
method_name |
方法名称 |
args |
调用参数,mc::variants(即 std::vector<mc::variant>),默认为空 |
mc::reflect::reflection_factory
// 头文件: <mc/reflect/reflection_factory.h>
class reflection_factory;
| 方法 | 参数 | 返回值 | 异常 | 线程安全 | 说明 |
|---|---|---|---|---|---|
global() |
无 | reflection_factory& |
不抛出 | 是 | 获取全局单例工厂 |
global_ptr() |
无 | factory_ptr& |
不抛出 | 是 | 获取全局工厂的 shared_ptr 引用 |
try_global_ptr() |
无 | factory_ptr |
不抛出 | 是 | 尝试获取全局工厂指针,不存在返回空 |
reset_global() |
无 | void |
不抛出 | 是 | 重置全局工厂(测试用) |
instance<NameSpace>() |
模板参数 | reflection_factory& |
不抛出 | 是 | 获取命名空间工厂单例。global_namespace 等同于 global() |
instance_ptr<NameSpace>() |
模板参数 | factory_ptr& |
不抛出 | 是 | 获取命名空间工厂 shared_ptr 引用 |
try_instance_ptr<NameSpace>() |
模板参数 | factory_ptr |
不抛出 | 是 | 尝试获取命名空间工厂,不存在返回空 |
get_metadata(type_id) |
type_id_type |
reflection_metadata_ptr |
可能抛出(类型不存在) | 否 | 按 type_id 获取反射元数据 |
get_metadata(type_name) |
mc::string_view |
reflection_metadata_ptr |
可能抛出(类型不存在) | 否 | 按类型名获取反射元数据 |
try_create_object(type_id) |
type_id_type |
reflected_object_ptr |
不抛出 | 否 | 尝试按 type_id 创建对象,失败返回空 |
try_create_object(type_name) |
mc::string_view |
reflected_object_ptr |
不抛出 | 否 | 尝试按类型名创建对象,失败返回空 |
try_create_object(type_name, init) |
mc::string_view, const mc::dict& |
reflected_object_ptr |
不抛出 | 否 | 尝试按类型名创建并注入 init 初值,失败返回空 |
create_object(type_id) |
type_id_type |
reflected_object_ptr |
可能抛出(类型不存在/抽象类) | 否 | 按 type_id 创建对象,失败抛出异常 |
create_object(type_name) |
mc::string_view |
reflected_object_ptr |
可能抛出(类型不存在/抽象类) | 否 | 按类型名创建对象,失败抛出异常 |
create_object(type_name, init) |
mc::string_view, const mc::dict& |
reflected_object_ptr |
可能抛出(类型不存在/抽象类) | 否 | 按类型名创建并注入 init 初值;注入语义由具体 metadata 决定(见 reflection_base::create_object(init)) |
get_type_id(type_name) |
mc::string_view |
type_id_type |
不抛出 | 是 | 按名称查询 type_id,不存在返回 INVALID_TYPE_ID |
get_registered_types() |
无 | std::vector<mc::string> |
不抛出 | 是 | 返回所有已注册类型名称 |
get_module_types(module_path) |
mc::string_view |
std::vector<mc::string> |
不抛出 | 是 | 返回指定模块路径下的类型名 |
register_type<T>(type_id) |
模板 + 可选 type_id | type_id_type |
可能抛出(重复注册) | 否 | 注册类型 T,可指定 type_id |
register_runtime_metadata(type_name, metadata) |
mc::string_view, reflection_metadata_ptr |
metadata_registration |
不抛出 | 是 | 运行时注册 metadata(动态语言运行期构造的类型)。工厂仅弱引用,强引用由返回句柄持有;类型名非法或重名返回空句柄 |
register_factory(factory) |
factory_ptr |
factory_id_type |
可能抛出(冲突时) | 否 | 注册子工厂 |
unregister_factory(name) |
mc::string_view |
void |
不抛出 | 否 | 注销子工厂 |
get_factory(name) |
mc::string_view |
factory_ptr |
可能抛出(不存在时) | 否 | 按名称获取子工厂 |
mc::reflect::metadata_registration
// 头文件: <mc/reflect/reflection_factory.h>
class metadata_registration; // 运行时 metadata 注册句柄(RAII,move-only)
由 reflection_factory::register_runtime_metadata 返回。句柄强持有 metadata,工厂内部仅弱引用;
句柄析构(或 reset())时自动从工厂注销并释放 metadata。工厂已先于句柄销毁时注销为安全 no-op。
| 方法 | 参数 | 返回值 | 异常 | 线程安全 | 说明 |
|---|---|---|---|---|---|
operator bool() |
无 | bool |
不抛出 | 是 | 句柄是否持有有效注册(注册失败时为 false) |
get_type_id() |
无 | type_id_type |
不抛出 | 是 | 工厂分配的类型 id(已编码 factory id);空句柄返回 INVALID_TYPE_ID |
get_metadata() |
无 | const reflection_metadata_ptr& |
不抛出 | 是 | 句柄持有的 metadata;空句柄返回空指针 |
reset() |
无 | void |
不抛出 | 是 | 提前注销并释放 metadata;重复调用安全 |
全局便捷函数:
// 头文件: <mc/reflect/reflection_factory.h>
MC_API reflected_object_ptr try_create_object(type_id_type type_id);
MC_API reflected_object_ptr try_create_object(mc::string_view type_name);
MC_API reflected_object_ptr create_object(type_id_type type_id);
MC_API reflected_object_ptr create_object(mc::string_view type_name);
template <typename T>
reflected_object_ptr wrap_object(std::shared_ptr<T> obj); // 将 shared_ptr 包装为 reflected_object_ptr
template <typename T>
reflected_object_ptr wrap_object(const T& obj); // 拷贝对象并包装
mc::reflect::reflection<T>
// 头文件: <mc/reflect/reflection.h>
template <typename T>
auto& get_reflection(); // 获取类型 T 的反射单例
结构体特化(reflection<T> 继承 struct_reflection_bridge):
| 方法 | 参数 | 返回值 | 异常 | 线程安全 | 说明 |
|---|---|---|---|---|---|
get_property_info(name) |
mc::string_view 或 mc::quark |
const property_info_base<T>* |
不抛出 | 是 | 按名称获取属性信息,不存在返回 nullptr |
get_property_info(offset) |
size_t |
const property_info_base<T>* |
不抛出 | 是 | 按偏移量获取属性信息,不存在返回 nullptr |
get_property(obj, key) |
const T&, mc::string_view |
mc::variant |
不抛出 | 否 | 获取属性值,不存在返回空 variant |
get_property(obj, key, base_name) |
const T&, mc::string_view, mc::string_view |
mc::variant |
不抛出 | 否 | 通过基类名获取属性值 |
get_all_properties(obj) |
const T& |
mc::dict |
不抛出 | 否 | 获取所有属性(含基类),返回 dict |
set_property(obj, key, value) |
T&, mc::string_view, const mc::variant& |
bool |
不抛出 | 否 | 设置属性值,成功返回 true |
invoke_method(obj, name, args) |
T&, mc::string_view, const mc::variants& |
mc::variant |
方法不存在时抛出 | 否 | 调用成员方法 |
invoke_method(name, args) |
mc::string_view, const mc::variants& |
mc::variant |
方法不存在或非静态时抛出 | 否 | 调用静态方法 |
async_invoke_method(obj, name, args) |
T&, mc::string_view, const mc::variants& |
async_result |
方法不存在时抛出 | 否 | 异步调用成员方法 |
get_property_name(offset) |
size_t |
mc::string_view |
不抛出 | 是 | 根据偏移量获取属性名 |
枚举特化(reflection<T> 继承 registered_reflection_bridge):
| 方法 | 参数 | 返回值 | 异常 | 线程安全 | 说明 |
|---|---|---|---|---|---|
get_enum_value(name) |
mc::string_view |
uint64_t |
可能抛出(值不存在) | 是 | 按名称获取枚举值 |
get_enum_name(value) |
uint64_t |
mc::string_view |
可能抛出(名称不存在) | 是 | 按值获取枚举名称 |
get_enum_names() |
无 | std::vector<mc::string_view> |
可能抛出(非枚举类型) | 是 | 获取所有枚举名称 |
has_enum_value(name) |
mc::string_view |
bool |
不抛出 | 是 | 检查枚举值是否存在(按名称) |
mc::reflect::reflection_base(抽象基类)
// 头文件: <mc/reflect/base.h>
class reflection_base : public mc::shared_base;
| 方法 | 参数 | 返回值 | 异常 | 线程安全 | 说明 |
|---|---|---|---|---|---|
get_type_name() |
无 | mc::string_view |
不抛出 | 是 | 获取反射类型名 |
get_type_id() |
无 | type_id_type |
不抛出 | 是 | 获取类型 ID |
get_base_type_ids() |
无 | std::vector<type_id_type> |
不抛出 | 是 | 获取所有基类 type_id |
is_derived_from(type_id) |
type_id_type |
bool |
不抛出 | 是 | 判断是否派生自指定类型 |
create_object() |
无 | mc::shared_ptr<reflected_object> |
可能抛出(抽象类/非结构体) | 否 | 创建动态反射对象 |
create_object(init) |
const mc::dict& |
mc::shared_ptr<reflected_object> |
可能抛出(抽象类/非结构体/属性不存在) | 否 | 带 init 的统一创建:底层对象构造完成后注入 init 初值(语义同「基类先构造并初始化,用户 ctor 后执行」)。默认实现先 create_object() 再逐项 set_property;子类可 override 实现「ctor 前注入」 |
visit_properties(visitor) |
property_visitor_t |
void |
不抛出(除非 visitor 抛出) | 否 | 遍历所有属性,visitor 返回 visit_status::VS_BREAK 可提前终止 |
visit_methods(visitor) |
method_visitor_t |
void |
不抛出(除非 visitor 抛出) | 否 | 遍历所有方法,可提前终止 |
visit_base_classes(visitor) |
base_class_visitor_t |
void |
不抛出(除非 visitor 抛出) | 否 | 遍历所有基类,可提前终止 |
visit_customs(visitor) |
custom_visitor_t |
void |
不抛出(除非 visitor 抛出) | 否 | 遍历所有自定义成员,可提前终止 |
get_property_info(name) |
mc::string_view 或 mc::quark |
const property_type_info* |
不抛出 | 是 | 查询属性信息 |
get_method_info(name) |
mc::string_view 或 mc::quark |
const method_type_info* |
不抛出 | 是 | 查询方法信息 |
get_base_class_info(name) |
mc::string_view 或 mc::quark |
const base_class_type_info* |
不抛出 | 是 | 查询基类信息 |
get_custom_info(name, reflect_type) |
mc::string_view 或 mc::quark, size_t |
const member_info_base* |
不抛出 | 是 | 查询自定义成员信息 |
get_property_names() |
无 | std::vector<mc::string_view> |
不抛出 | 是 | 获取所有属性名 |
get_method_names() |
无 | std::vector<mc::string_view> |
不抛出 | 是 | 获取所有方法名 |
is_enum() |
无 | bool |
不抛出 | 是 | 是否为枚举类型 |
get_enum_value(name) |
mc::string_view |
uint64_t |
非枚举类型调用时抛出 | 是 | 枚举值查询(基类默认抛出) |
get_enum_name(value) |
uint64_t |
mc::string_view |
非枚举类型调用时抛出 | 是 | 枚举名查询(基类默认抛出) |
get_enum_names() |
无 | std::vector<mc::string_view> |
非枚举类型调用时抛出 | 是 | 获取所有枚举名(基类默认抛出) |
has_enum_value(name/value) |
mc::string_view 或 uint64_t |
bool |
非枚举类型调用时抛出 | 是 | 检查枚举值是否存在(基类默认抛出) |
visit_* 的 visitor 类型签名(返回 visit_status 控制遍历):
enum class visit_status { VS_CONTINUE, VS_BREAK };
using property_visitor_t = std::function<visit_status(const property_type_info*)>;
using method_visitor_t = std::function<visit_status(const method_type_info*)>;
using base_class_visitor_t = std::function<visit_status(const base_class_type_info*)>;
using custom_visitor_t = std::function<visit_status(const member_info_base*)>;
mc::reflect::reflected_object(动态对象接口)
// 头文件: <mc/reflect/base.h>
class reflected_object : public mc::shared_base; // 侵入式引用计数,由 mc::shared_ptr 持有
using reflected_object_ptr = mc::shared_ptr<reflected_object>;
说明:
reflected_object继承mc::shared_base,与reflection_base、struct_metadata统一为mc::shared_ptr体系(不再使用std::shared_ptr),消除双指针体系,使反射对象 能原生交由 Lua(luaclib/mc)等侧共同管理生命周期。
| 方法 | 参数 | 返回值 | 异常 | 线程安全 | 说明 |
|---|---|---|---|---|---|
get_type_id() |
无 | type_id_type |
不抛出 | 是 | 获取运行时类型 ID |
get_property(name) |
mc::string_view |
variant |
可能抛出(属性不存在/转换失败) | 否 | 获取属性值 |
set_property(name, value) |
mc::string_view, const variant& |
void |
可能抛出(属性不存在/类型不匹配) | 否 | 设置属性值 |
invoke_method(name, args) |
mc::string_view, const std::vector<variant>& |
variant |
可能抛出(方法不存在/参数不匹配) | 否 | 调用方法 |
async_invoke_method(name, args) |
mc::string_view, const std::vector<variant>& |
async_result |
可能抛出(方法不存在) | 否 | 异步调用方法 |
get_property_names() |
无 | std::vector<mc::string_view> |
不抛出 | 是 | 获取所有属性名 |
get_method_names() |
无 | std::vector<mc::string_view> |
不抛出 | 是 | 获取所有方法名 |
mc::reflect::struct_metadata
// 头文件: <mc/reflect/metadata.h>
class struct_metadata;
| 方法 | 参数 | 返回值 | 异常 | 线程安全 | 说明 |
|---|---|---|---|---|---|
get_name() |
无 | mc::string_view |
不抛出 | 是 | 返回类型名 |
get_type_id() |
无 | type_id_type |
不抛出 | 是 | 返回类型 ID |
get_property_info(name) |
mc::string_view 或 mc::quark |
const property_type_info* |
不抛出 | 是 | 按名称查找属性 |
get_property_info(offset) |
size_t |
const property_type_info* |
不抛出 | 是 | 按偏移查找属性 |
get_method_info(name) |
mc::string_view 或 mc::quark |
const method_type_info* |
不抛出 | 是 | 按名称查找方法 |
get_base_class_info(name) |
mc::string_view 或 mc::quark |
const base_class_type_info* |
不抛出 | 是 | 按名称查找基类 |
visit_properties(visitor) |
property_visitor_t |
void |
不抛出 | 否 | 遍历所有属性 |
visit_methods(visitor) |
method_visitor_t |
void |
不抛出 | 否 | 遍历所有方法 |
visit_base_classes(visitor) |
base_class_visitor_t |
void |
不抛出 | 否 | 遍历所有基类 |
get_base_type_ids() |
无 | std::vector<type_id_type> |
不抛出 | 是 | 获取所有基类 type_id |
is_derived_from(type_id) |
type_id_type |
bool |
不抛出 | 是 | 是否派生自指定类型 |
get_property_names() |
无 | std::vector<mc::string_view> |
不抛出 | 是 | 获取所有属性名 |
get_method_names() |
无 | std::vector<mc::string_view> |
不抛出 | 是 | 获取所有方法名 |
add_runtime_property_info(property) |
const property_type_info* |
void |
分配失败抛 std::bad_alloc |
否 | 运行时追加属性,调用方持有 info 生命周期 |
add_runtime_method_info(method) |
const method_type_info* |
void |
同上 | 否 | 运行时追加方法,调用方持有 info 生命周期 |
add_runtime_custom_info(custom) |
const member_info_base* |
void |
同上 | 否 | 运行时追加自定义成员 |
add_runtime_owned_property_info(property) |
const property_type_info* |
void |
同上 | 否 | 运行时追加属性,struct_metadata 接管 info 生命周期 |
add_runtime_owned_method_info(method) |
const method_type_info* |
void |
同上 | 否 | 运行时追加方法,struct_metadata 接管 info 生命周期 |
finish_runtime_members() |
无 | void |
不抛出 | 否 | 运行时成员添加完毕后调用,恢复成员有序性 |
注:struct_metadata 继承 mc::shared_base,可由 mc::shared_ptr 持有(运行时动态构造场景,如 mcengine 的 runtime_object);method_type_info 新增虚函数 is_variadic()(默认 false),运行时注册的变参动态方法可覆写为 true。
mc::reflect::enum_metadata
// 头文件: <mc/reflect/metadata.h>
class enum_metadata;
| 方法 | 参数 | 返回值 | 异常 | 线程安全 | 说明 |
|---|---|---|---|---|---|
get_value(name) |
mc::string_view |
enum_value_type |
名称不存在时抛出 | 是 | 按名称获取枚举值 |
get_value_from_variant(var) |
const mc::variant& |
enum_value_type |
variant 无法转换时抛出 | 是 | 从 variant 获取枚举值 |
get_name(value) |
enum_value_type |
mc::string_view |
值不存在时抛出 | 是 | 按值获取枚举名称 |
try_get_value(name) |
mc::string_view |
std::optional<enum_value_type> |
不抛出 | 是 | 安全按名称查询枚举值 |
try_get_value_from_variant(var) |
const mc::variant& |
std::optional<enum_value_type> |
不抛出 | 是 | 安全从 variant 查询枚举值 |
try_get_name(value) |
enum_value_type |
std::optional<mc::string_view> |
不抛出 | 是 | 安全按值查询枚举名称 |
has_value(name) |
mc::string_view |
bool |
不抛出 | 是 | 检查枚举值是否存在(按名称) |
has_value(value) |
enum_value_type |
bool |
不抛出 | 是 | 检查枚举值是否存在(按值) |
get_names() |
无 | std::vector<mc::string_view> |
不抛出 | 是 | 获取所有枚举名称 |
get_values() |
无 | enum_values |
不抛出 | 是 | 获取所有枚举值-名称对 |
类型信息结构
// 头文件: <mc/reflect/metadata_info.h>
using enum_value_type = uint32_t;
struct enum_member_info {
mc::string_view name;
enum_value_type value;
};
struct property_type_info : public member_info_base {
mc::variant get_value(const void* obj) const;
void set_value(void* obj, const mc::variant&) const;
bool is_writable() const noexcept;
};
struct method_type_info : public member_info_base {
size_t arg_count() const;
mc::variant invoke(void* obj, const mc::variants&) const;
async_result async_invoke(void* obj, const mc::variants&) const;
bool is_static() const;
};
struct base_class_type_info : public member_info_base {
type_id_type get_type_id() const;
mc::variant get_value(void* obj, mc::string_view name) const;
void set_value(void* obj, mc::string_view name, const mc::variant&) const;
};
struct member_info_base {
mc::string_view name;
uint32_t flags;
uint32_t base_offset;
uint64_t data;
};
核心类型别名与常量
// 头文件: <mc/reflect/base.h>
using type_id_type = int64_t;
using local_type_id_type = int32_t;
using factory_id_type = int32_t;
constexpr type_id_type INVALID_TYPE_ID = -1;
constexpr factory_id_type INVALID_FACTORY_ID = -1;
using reflected_object_ptr = mc::shared_ptr<reflected_object>;
using reflection_metadata_ptr = mc::shared_ptr<reflection_base>;
using reflection_metadata_wptr = mc::weak_ptr<reflection_base>;
using async_result = mc::result<mc::variant>;
最佳实践
✅ 将 MC_REFLECTABLE 放在类定义的起始位置
struct MyData {
MC_REFLECTABLE("MyData") // ← 第一行,紧跟 public: 之后
// 或直接在 struct 默认 public 下首行
int id;
std::string name;
};
MC_REFLECT(MyData, id, name)
MC_REFLECTABLE 必须在类内定义 friend 声明和类型别名,放在最前面避免与其它声明产生顺序依赖。
✅ 对枚举使用 try_get_value / try_get_name 进行安全查询
auto& meta = mc::reflect::reflector<Color>::get_metadata();
// ✅ 安全模式:先检查再取值
if (auto v = meta.try_get_value("红色")) {
Color c = static_cast<Color>(*v);
// 使用 c...
}
// ✅ 有默认值时的模式
auto val = meta.try_get_value("未知色").value_or(0);
❌ 在头文件中直接调用 MC_REFLECT 而非 .cpp 或全局作用域
// ❌ 错误:在函数体内调用 MC_REFLECT
void setup() {
MC_REFLECT(MyData, id, name) // 编译错误:宏展开为全局模板特化
}
MC_REFLECT 展开为全局命名空间的模板特化,必须在全局作用域(或 mc::reflect 命名空间内)调用。
❌ 忘记声明 MC_REFLECTABLE 而直接使用 MC_REFLECT
// ❌ 错误:缺少 MC_REFLECTABLE
struct Bad {
int value;
};
MC_REFLECT(Bad, value)
// 编译错误:static_assert "Bad is not reflectable"
MC_REFLECT 内部会 static_assert 检查类型是否已通过 MC_REFLECTABLE 声明。必须先声明再定义。
✅ 使用自定义序列化覆盖默认行为
struct Versioned {
MC_REFLECTABLE("Versioned")
int version = 1;
int value = 0;
// 自定义序列化逻辑:可添加版本字段
static void to_variant(const Versioned& self, mc::dict& dict) {
dict("version", self.version)("value", self.value);
}
static void from_variant(const mc::dict& dict, Versioned& self) {
self.version = dict["version"].as<int>();
self.value = dict["value"].as<int>();
}
};
// 仍然需要 MC_REFLECT(即使为空)
MC_REFLECT(Versioned)
提供静态 to_variant / from_variant 方法时,reflector<T> 会自动优先使用,无需注册。
❌ 在 MC_REFLECT 中混用不同类型的成员
// ❌ 错误:方法名和字段名相同会造成歧义
struct Ambiguous {
MC_REFLECTABLE("Ambiguous")
int value;
int value() const { return 0; }
};
MC_REFLECT(Ambiguous, value, value) // 两个 value —— 二义
当方法和字段同名时,MC_REFLECT 宏展开中两者都会被注册,运行时按顺序匹配第一个,可能导致非预期行为。建议给字段加后缀或给方法改名。
✅ 使用 MC_REFLECT_WITH_NAMESPACE 隔离不同模块的类型
// 在模块 A
struct MyNamespace {
constexpr static mc::string_view factory_name = "ModuleA";
};
struct TypeA {
MC_REFLECTABLE("ModuleA.TypeA")
int x;
};
MC_REFLECT_WITH_NAMESPACE(MyNamespace, TypeA, x)
// 在模块 B
struct TypeB {
MC_REFLECTABLE("ModuleB.TypeB")
int y;
};
MC_REFLECT_WITH_NAMESPACE(MyNamespace, TypeB, y)
// 获取特定命名空间的工厂
auto& factory = mc::reflect::reflection_factory::instance<MyNamespace>();
auto obj = factory.create_object("ModuleA.TypeA");