我正在创建一个编辑数据的应用程序,然后需要以各种格式存储它。问题是应用程序是使用插件架构构建的 记住,所以我不知道哪些格式或哪些对象需要事先存储。
我想要完成的是一个SerializeManager,您可以在其中动态注册支持的格式。
目标是能够创建一个对象,然后指定模板特化支持的格式。 例如:
template<typename Type, typename Format>
void serialize(const Type& type, const Format& format)
{
}
class IFormat
{
public:
virtual ~IFormat(){}
};
class XmlFormat : public IFormat
{
};
class BinaryFormat : public IFormat
{
};
class MyDataToStore
{
public:
int m_data1; //Data to store
string m_data2; //Data to store
};
template<>
void serialize(const MyDataToStore& type, const XmlFormat& format)
{
//Serialization code goes here
}
我现在的目标是创建一个SerializeManager来管理所有格式并调用正确的特化。我希望它能像这样工作:
int main()
{
SerializeManager man;
man.RegisterFormat(".xml", std::shared_ptr<IFormat>(new XmlFormat())); // Where .xml is a key
MyDataToStore obj;
man.Store<MyDataToStore>(".xml", obj); //where .xml is a key
}
目标是在上面的MyDataToStore,Xml特化中结束,而不必在Store函数中将格式指定为模板参数。这甚至可能吗?我已经尝试在IFormat类中使用纯虚函数来调用子类中的serialize函数,但由于虚函数无法使用模板,因此我松开MyDataToStore并调用默认函数。
问候!
编辑:
如果有人想知道我使用以下解决方案解决了问题。我不想在序列化/反序列化时只需指定扩展名。这是我的结果。
#include <string>
template<typename Formatter, typename Type>
void serialize(Formatter& format, Type& type)
{
static_assert(false, "No known serializer function found");
}
template<typename Formatter, typename Type>
void deserialize(Formatter& format, Type& type)
{
static_assert(false, "No known deserializer function found");
}
class SerializeManager
{
public:
SerializeManager(){}
virtual ~SerializeManager(){}
template<typename Type, typename Formatter>
bool Serialize(std::string filepath, Type & t)
{
Formatter format(filepath);
format.setManager(this);
serialize<Formatter, Type>(format, t);
return true;
}
template<typename Type, typename Formatter>
bool Serialize(Formatter& format, Type& t)
{
serialize(format, t);
return true;
}
template<typename Type, typename Formatter>
bool Deserialize(std::string filepath, Type & t)
{
Formatter format(filepath);
format.setManager(this);
deserialize<Formatter, Type>(format, t);
return true;
}
template<typename Type, typename Formatter>
bool Deserialize(Formatter& format, Type& t)
{
deserialize(format, t);
return true;
}
private:
};
class FormatterBase
{
public:
void setManager(SerializeManager* man)
{
m_manager = man;
}
SerializeManager* getManager()
{
return m_manager;
}
private:
SerializeManager* m_manager;
};
如果没有找到专门的函数,static_assert会帮助引发编译器错误。似乎运作良好。用法:
#include "SerializeManager.h"
struct Human
{
template<typename T, typename S>
friend void serialize(T& t, S& s);
template<typename T, typename S>
friend void deserialize(T& t, S& s);
Human(int age, std::string name) : m_age(age), m_name(name){}
private:
int m_age;
std::string m_name;
};
class XmlSerializer : public FormatterBase
{
public:
XmlSerializer(std::string filepath){}
void NewNode(std::string name){}
};
template<>
void serialize(XmlSerializer& serial, Human& human)
{
//Do the serialization
}
int main()
{
SerializeManager man;
Human åke(15, "Åke");
man.Serialize<Human, XmlSerializer>("file.xml", åke);
}
答案 0 :(得分:2)
我认为你在步行之前就已经开始了。
您需要的是中间格式。它可以是二进制的,它可以是名称/值对的树,它并不重要。什么重要是所有内容都可以序列化为这种中间格式。
然后,在这种中间格式中编写序列化器是一个简单的(ha!)案例。你可以想出Xml,Json,Binary或其他任何深奥的格式。
关键是众所周知且定义明确的中间层。一旦你拥有了它,那么在另一端发生的事情并不重要。