我有一个Serialization接口,用于封装我的应用程序的XML / JSON /二进制序列化之间的差异。它看起来像这样:
interface Serialization {
bool isObject();
int opApply(int delegate(string member, Serialization value) del); //iterate object
...
int toInt(); //this part is ugly, but without template member overloading, I
long toLong(); //figure out any way to apply generics here, so all basic types
... //have a toType primitive
string toString();
}
class JSONSerialization : Serialization {
private JSON json;
...
long toLong() {
enforce(json.type == JSON_TYPE.NUMBER, SerializationException.IncorrectType);
return cast(long)json.toNumber();
}
...
}
那么,我接下来设置的是一组用于注册类型反序列化器并调用它们的模板:
...
registerTypeDeserializer!Vec3(delegate Vec3(Serialization s) {
return Vec3(s[0].toFloat, s[1].toFloat, s[2].toFloat);
});
...
auto v = parseJSON("some file").deserialize!Vec3;
...
registerTypeDeserializer!Light(delegate Light(Serialization s) {
return new Light(s["intensity"].toFloat, s["position"].deserialize!Vec3);
});
这适用于结构和简单类,并且使用新参数标识符元组和参数默认值元组,我甚至应该能够添加自动反序列化器生成。但是,我并不喜欢基本类型和用户定义类型之间的不一致,更重要的是,复杂类型必须依赖全局状态来获取引用:
static MaterialLibrary materials;
registerTypeDeserializer!Model(delegate Model(Serialization s) {
return new Model(materials.borrow(s["material"].toString), ...);
});
这就是真正崩溃的地方。因为我不能(没有寄存器反序列化函数的扩散)将其他参数传递给反序列化器,所以我很难避免丑陋的全局工厂。我已经考虑过消除反序列化模板,并且需要为每个用户定义的类型提供反序列化函数(可以接受多个参数),但这似乎是很多工作。 POD结构。
那么,我如何简化这种设计,并希望避免大量的样板反序列化器,同时仍允许我适当地注入对象工厂,而不是全局分配它们?
答案 0 :(得分:2)
可以使用readf
\ formattedRead
读取基本类型,因此您可以创建一个使用此formattedRead
的包装函数,否则它将使用所需类型的静态函数读取值。像这样:
auto _readFrom(T)(string s){
static if(__traits(compiles,(readf("",cast(T*)(null))))){
T result;
formattedRead(s,"%s",&result);
return result;
}else{
return T.readFrom(s);
}
}