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");