奇异模板加编译时自省加静态构造是成功,以自动序化,解序为例
原文地址
作者:h.s.teoh
最近,我需要扩展简单序化系统,来处理多态对象.
昨天,我发现个优秀解决方案:用crtp(奇异递归模板),来注入方法至继承类.
class Saveable(Derived, Base) : Base {
static if (is(Base == Object)) {//基类
// 顶级虚函数
void save() { ... }
} else {
//继承类,盖
override void save() { ... }
}
}
class Base : Saveable!(Base, Object) { ... }
class Derived1 : Saveable!(Derived1, Base) { ... }
class Derived2 : Saveable!(Derived1, Base) { ... }
奇异声明在类的第1行,很难丢失.可保存的基参数,使我们容易注入盖方法至类层次,并区别基类/继承类.
可保存的保存方法,用模板参数来自省继承类并生成序化字段代码.在序化输出中它包含生成标识类型的标签的代码.从而完成了一半序化.
为了解序,可以用对象.工厂.但接口太旧,且从正确类型中读回字段有断开,因而可以用静态构造器来修复.
alias Loader = Object function(InputFile);
Loader[string] classLoaders;
class Saveable(Derived, Base) : Base {
static if (is(Base == Object)) {//基类
// 顶级虚函数
void save() { ... }
} else {
//继承类,盖
override void save() { ... }
}
static this()//静态构造器.
{
classLoaders[Derived.stringof] = (InputFile f) {
auto result = new Derived;
... //用自省来读回继承的字段
return result;
};
}
}
这儿神奇的地方是,每个可保存的实例生成一个静 本()块,有继承类的全部编译时信息.所以函数字面可用编译时自省来生成可序化代码.然后通过以类名作为键来注册函数字面进全局加载表.(为了简单,这里我用.的串,对大规模项目,你可用.的混杂).
因为,静 本块在启动程序,加载动态库时运行.确保启动程序后类加载器有程序要用的所有信息.所以解序代码可简单在类加载器中查找保存的类型签.并调用函数指针来重构对象.结果是,为可序化任何类,你只需要用:
class MyClass : Saveable!(MyClass, MyBase) { ... }
替换:
class MyClass : MyBase { ... }
其他所有全部自动搞好.不需要插件,重复序化类,运行时类型信息,甚至还支持动态库加载的类定义.只要你用Runtime.loadLibrary来确保运行静态构造器.因为静态构造器会注入任何新类加载器至类加载器.并自动教会解序代码如何解序.
奇异模板+编译时自省+静态构造==成功!
浙公网安备 33010602011771号