Extra2D/include/module/module_registry.h

112 lines
2.8 KiB
C++

#pragma once
#include <functional>
#include <memory>
#include <module/module.h>
#include <string>
#include <typeindex>
#include <vector>
namespace extra2d {
/**
* @brief 模块工厂函数类型
*/
using ModuleFactory = std::function<std::unique_ptr<Module>()>;
/**
* @brief 模块注册信息
*/
struct ModuleInfo {
std::string name;
ModuleFactory factory;
int32 priority;
std::type_index type;
};
/**
* @brief 模块注册表
*
* 支持自动模块注册和获取
* 使用服务定位器模式
*/
class ModuleRegistry {
public:
/**
* @brief 获取全局注册表实例
*/
static ModuleRegistry &instance();
/**
* @brief 注册模块类型
* @tparam T 模块类型
* @param name 模块名称
* @param priority 初始化优先级
*/
template <typename T>
void registerModule(const char *name, int32 priority = 100) {
static_assert(std::is_base_of_v<Module, T>, "T must inherit from Module");
ModuleInfo info{
name, []() -> std::unique_ptr<Module> { return std::make_unique<T>(); },
priority, std::type_index(typeid(T))};
registrations_.push_back(std::move(info));
}
/**
* @brief 创建所有已注册的模块
* @return 创建的模块列表(已按优先级排序)
*/
std::vector<std::unique_ptr<Module>> createModules();
/**
* @brief 获取已注册的模块信息列表
*/
const std::vector<ModuleInfo> &getRegistrations() const {
return registrations_;
}
private:
ModuleRegistry() = default;
std::vector<ModuleInfo> registrations_;
};
/**
* @brief 自动模块注册辅助类
*/
template <typename T> class ModuleRegistrar {
public:
ModuleRegistrar(const char *name, int32 priority = 100) {
ModuleRegistry::instance().registerModule<T>(name, priority);
}
};
/**
* @brief 模块注册宏
*
* 在模块类定义中使用,实现自动注册
* 示例:
* class MyModule : public Module {
* E2D_REGISTER_MODULE(MyModule, "MyModule", 10)
* public:
* // ...
* };
*/
#define E2D_REGISTER_MODULE(ClassName, Name, Priority) \
private: \
static inline const extra2d::ModuleRegistrar<ClassName> _registrar{ \
Name, Priority}; \
\
public: \
const char *getName() const override { return Name; } \
int32 getPriority() const override { return Priority; }
/**
* @brief 简化版模块注册宏(使用类名作为模块名)
*/
#define E2D_REGISTER_MODULE_SIMPLE(ClassName) \
E2D_REGISTER_MODULE(ClassName, #ClassName, 100)
} // namespace extra2d