我正在尝试将我的框架的一部分从 Python 转换为 D,并且正在努力解决一个细节:但首先我必须扩大范围。该组件就像一个 ORM。我的用户定义类,哪些实例将在数据库中持久存在。用户 API 应该尽可能简单。例如
class Person:
identity _id,
string name,
date birthdate,
...
class Car:
indentity _id,
string ident,
int power,
Person owner
...
myCar = Car.load(ident="DEAD-BEAF")
print myCar.power
print myCar.owner.name
加载函数从数据库加载实例数据。但是车主的加载应该推迟到实例被使用,因为大多数应用程序都工作在汽车上,车主很少使用。
在 Python 中,我可以使用Descriptor-Protocol来实现这种行为。我有一组“字段”类,它们是描述符。例如
class StringField(object):
def __get__(self,obj,objtype):
# get the value from obj
def __set__(self,obj,value):
# set value in obj
EntityClass 有一个适当的元类,它连接所需的连接。用户在 Python 中定义:
class Person(EntityClass):
name = StringField()
birthdate = DateField()
...
class Car(EntityClass):
ident = StringField()
power = IntField()
owner = RelationField(Person)
...
并使用类:
myCar = Car.load(ident="DEAD-BEAF")
print myCar.power (#1)
print myCar.owner.name (#2)
在引擎盖下,对 myCar.power 的调用扩展到
Car.power.__get__(myCar,Car)
如果我从数据库加载汽车,我只加载所有者 ID。如果一个使用所有者
theowner = myCar.owner
我可以从数据库中加载延迟的 Person 实例
class RelationField(object):
def __get__(self,obj,objtype):
if not instance in obj.cache:
load instance
add instance to obj.cache
return instance from obj.cache
将 ORM 转换为 DI 尝试了不同的实现。对于简单的基本类型,将用户定义的属性 (UDA) 与模板和统一调用语法结合使用非常简单:
struct Persistent {};
save(T)(ref T obj)
{
...
}
T load(T)(...)
class Person
{
@Persistent string name;
@Persistent Date birthday;
...
}
class Car
{
@Persistent string ident;
@Persistent int power;
@Persistent Person owner; //???
...
}
auto myCar = load!Car(...);
writeln(myCar.power);
writeln(myCar.owner.name)
这个 API 和 Python-API 一样简单,但是我不知道如何实现 owner 的延迟加载。我需要的是用属性函数替换所有者成员,但我不知道如何使用编译时元编程来做到这一点。那么这要怎么做呢?还是有惯用的方法?