如何简化反序列化框架?

时间:2012-07-18 20:03:23

标签: serialization d

我有一个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结构。

那么,我如何简化这种设计,并希望避免大量的样板反序列化器,同时仍允许我适当地注入对象工厂,而不是全局分配它们?

1 个答案:

答案 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);
    }
}