refactor(service): service instantiation to use instance constructor field
This commit is contained in:
parent
923c1c99b4
commit
36397c1119
7 changed files with 69 additions and 23 deletions
|
@ -23,12 +23,19 @@ typedef std::shared_ptr<Instance>(*InstanceConstructor)();
|
|||
class DataModel;
|
||||
class Workspace;
|
||||
|
||||
typedef int InstanceFlags;
|
||||
// This instance should only be instantiated in special circumstances (i.e. by DataModel) and should be creatable directly via any API
|
||||
const InstanceFlags INSTANCE_NOTCREATABLE = (InstanceFlags)0x1;
|
||||
// This instance is a service
|
||||
const InstanceFlags INSTANCE_SERVICE = (InstanceFlags)0x2;
|
||||
|
||||
// Struct describing information about an instance
|
||||
struct InstanceType {
|
||||
const InstanceType* super; // May be null
|
||||
std::string className;
|
||||
InstanceConstructor constructor;
|
||||
std::string explorerIcon = "";
|
||||
InstanceFlags flags;
|
||||
};
|
||||
|
||||
class DescendantsIterator;
|
||||
|
|
|
@ -1,9 +1,20 @@
|
|||
#include "service.h"
|
||||
#include "logger.h"
|
||||
#include "panic.h"
|
||||
#include <memory>
|
||||
|
||||
Service::Service(const InstanceType* type, std::weak_ptr<DataModel> root) : Instance(type), dataModel(root) {}
|
||||
Service::Service(const InstanceType* type) : Instance(type){}
|
||||
|
||||
// Fail if parented to non-datamodel, otherwise lock parent
|
||||
void Service::OnParentUpdated(std::optional<std::shared_ptr<Instance>> oldParent, std::optional<std::shared_ptr<Instance>> newParent) {
|
||||
if (!newParent || newParent.value()->GetClass() != &DataModel::TYPE) {
|
||||
Logger::fatalErrorf("Service %s was parented to object of type %s", GetClass()->className, newParent ? newParent.value()->GetClass()->className : "NULL");
|
||||
panic();
|
||||
}
|
||||
|
||||
// Prevent parent from being updated
|
||||
parentLocked = true;
|
||||
}
|
||||
|
||||
void Service::InitService() {
|
||||
SetParent(dataModel.lock());
|
||||
parentLocked = true;
|
||||
}
|
|
@ -6,10 +6,10 @@
|
|||
#include <memory>
|
||||
class Service : public Instance {
|
||||
protected:
|
||||
std::weak_ptr<DataModel> dataModel;
|
||||
|
||||
Service(const InstanceType* type, std::weak_ptr<DataModel> root);
|
||||
Service(const InstanceType* type);
|
||||
virtual void InitService();
|
||||
|
||||
void OnParentUpdated(std::optional<std::shared_ptr<Instance>> oldParent, std::optional<std::shared_ptr<Instance>> newParent) override;
|
||||
|
||||
friend class DataModel;
|
||||
};
|
|
@ -2,6 +2,7 @@
|
|||
#include "base/service.h"
|
||||
#include "objects/base/instance.h"
|
||||
#include "objects/base/service.h"
|
||||
#include "objects/meta.h"
|
||||
#include "workspace.h"
|
||||
#include "logger.h"
|
||||
#include "panic.h"
|
||||
|
@ -10,12 +11,6 @@
|
|||
#include <memory>
|
||||
#include <functional>
|
||||
|
||||
// TODO: Move this to a different file
|
||||
// ONLY add services here, all types are expected to inherit from Service, or errors WILL occur
|
||||
std::map<std::string, std::function<std::shared_ptr<Service>(std::weak_ptr<DataModel>)>> SERVICE_CONSTRUCTORS = {
|
||||
{ "Workspace", &Workspace::Create },
|
||||
};
|
||||
|
||||
const InstanceType DataModel::TYPE = {
|
||||
.super = &Instance::TYPE,
|
||||
.className = "DataModel",
|
||||
|
@ -33,8 +28,10 @@ DataModel::DataModel()
|
|||
|
||||
void DataModel::Init() {
|
||||
// Create the workspace if it doesn't exist
|
||||
if (this->services.count("Workspace") == 0)
|
||||
this->services["Workspace"] = std::make_shared<Workspace>(shared<DataModel>());
|
||||
if (this->services.count("Workspace") == 0) {
|
||||
this->services["Workspace"] = std::make_shared<Workspace>();
|
||||
AddChild(this->services["Workspace"]);
|
||||
}
|
||||
|
||||
// Init all services
|
||||
for (auto [_, service] : this->services) {
|
||||
|
@ -67,7 +64,7 @@ void DataModel::SaveToFile(std::optional<std::string> path) {
|
|||
|
||||
void DataModel::DeserializeService(pugi::xml_node* node) {
|
||||
std::string className = node->attribute("class").value();
|
||||
if (SERVICE_CONSTRUCTORS.count(className) == 0) {
|
||||
if (INSTANCE_MAP.count(className) == 0) {
|
||||
Logger::fatalErrorf("Unknown service: '%s'", className.c_str());
|
||||
panic();
|
||||
}
|
||||
|
@ -78,7 +75,8 @@ void DataModel::DeserializeService(pugi::xml_node* node) {
|
|||
}
|
||||
|
||||
// This will error if an abstract instance is used in the file. Oh well, not my prob rn.
|
||||
InstanceRef object = SERVICE_CONSTRUCTORS[className](shared<DataModel>());
|
||||
InstanceRef object = INSTANCE_MAP[className]->constructor();
|
||||
AddChild(object);
|
||||
|
||||
// Read properties
|
||||
pugi::xml_node propertiesNode = node->child("Properties");
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
#pragma once
|
||||
|
||||
#include "base.h"
|
||||
#include "logger.h"
|
||||
#include "objects/base/instance.h"
|
||||
#include "objects/meta.h"
|
||||
#include "panic.h"
|
||||
#include <memory>
|
||||
|
||||
class Workspace;
|
||||
|
||||
class DataModel;
|
||||
class Service;
|
||||
extern std::map<std::string, std::function<std::shared_ptr<Service>(std::weak_ptr<DataModel>)>> SERVICE_CONSTRUCTORS;
|
||||
|
||||
// The root instance to all objects in the hierarchy
|
||||
class DataModel : public Instance {
|
||||
|
@ -26,12 +29,37 @@ public:
|
|||
static inline std::shared_ptr<DataModel> New() { return std::make_shared<DataModel>(); };
|
||||
virtual const InstanceType* GetClass() override;
|
||||
|
||||
// Inserts a service if it doesn't already exist
|
||||
bool InsertService(std::string name) {
|
||||
if (services.count(name) != 0)
|
||||
return false;
|
||||
|
||||
if (!INSTANCE_MAP[name] || (INSTANCE_MAP[name]->flags ^ (INSTANCE_NOTCREATABLE | INSTANCE_SERVICE)) != 0) {
|
||||
Logger::fatalErrorf("Attempt to create instance of unknown type %s", name);
|
||||
panic();
|
||||
}
|
||||
|
||||
services[name] = std::dynamic_pointer_cast<Service>(INSTANCE_MAP[name]->constructor());
|
||||
AddChild(std::dynamic_pointer_cast<Instance>(services[name]));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::shared_ptr<T> GetService(std::string name) {
|
||||
if (services.count(name) != 0)
|
||||
return services[name];
|
||||
// TODO: Validate name
|
||||
services[name] = SERVICE_CONSTRUCTORS[name](shared<DataModel>());
|
||||
|
||||
// TODO: Replace this with a result return type
|
||||
if (!INSTANCE_MAP[name] || (INSTANCE_MAP[name]->flags ^ (INSTANCE_NOTCREATABLE | INSTANCE_SERVICE)) != 0) {
|
||||
Logger::fatalErrorf("Attempt to create instance of unknown type %s", name);
|
||||
panic();
|
||||
}
|
||||
|
||||
services[name] = std::dynamic_pointer_cast<Service>(INSTANCE_MAP[name]->constructor());
|
||||
AddChild(std::dynamic_pointer_cast<Instance>(services[name]));
|
||||
|
||||
return services[name];
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
#include "workspace.h"
|
||||
#include "objects/base/instance.h"
|
||||
|
||||
const InstanceType Workspace::TYPE = {
|
||||
.super = &Instance::TYPE,
|
||||
.className = "Workspace",
|
||||
// .constructor = &Workspace::Create,
|
||||
.constructor = &Workspace::Create,
|
||||
.explorerIcon = "workspace",
|
||||
.flags = INSTANCE_NOTCREATABLE | INSTANCE_SERVICE,
|
||||
};
|
||||
|
||||
const InstanceType* Workspace::GetClass() {
|
||||
return &TYPE;
|
||||
}
|
||||
|
||||
Workspace::Workspace(std::weak_ptr<DataModel> dataModel): Service(&TYPE, dataModel) {
|
||||
Workspace::Workspace(): Service(&TYPE) {
|
||||
}
|
||||
|
|
|
@ -9,9 +9,9 @@ class Workspace : public Service {
|
|||
public:
|
||||
const static InstanceType TYPE;
|
||||
|
||||
Workspace(std::weak_ptr<DataModel> dataModel);
|
||||
Workspace();
|
||||
|
||||
// static inline std::shared_ptr<Workspace> New() { return std::make_shared<Workspace>(); };
|
||||
static inline std::shared_ptr<Service> Create(std::weak_ptr<DataModel> parent) { return std::make_shared<Workspace>(parent); };
|
||||
static inline std::shared_ptr<Instance> Create() { return std::make_shared<Workspace>(); };
|
||||
virtual const InstanceType* GetClass() override;
|
||||
};
|
Loading…
Add table
Reference in a new issue