1

我有一个序列化接口,旨在为我的应用程序封装 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 结构来说似乎需要做很多工作。

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

4

1 回答 1

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);
    }
}
于 2012-07-19T02:35:44.040 回答