フレームワークの一部を Python から D に変換しようとしていますが、1 つの詳細に苦労しています。しかし、最初にスコープを拡張する必要があります。コンポーネントは 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
load-function は、データベースからインスタンス データをロードします。ただし、ほとんどのアプリケーションは車で動作し、所有者はめったに使用されないため、車の所有者のロードはインスタンスが使用されるまで延期する必要があります。
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 と同じくらい単純ですが、所有者の遅延読み込みを実装する方法がわかりません。所有者メンバーをプロパティ関数に置き換える必要がありますが、コンパイル時のメタ プログラミングを使用してこれを行う方法がわかりません。では、これはどのように行われるのでしょうか?または、慣用的な方法はありますか?