私のフレームワークの一部をPythonからDに翻訳しようとしていて、一つの細部に苦労しています。しかし、まずスコープを広げなければなりません。コンポーネントはORMに似ています。ユーザーはクラスを定義します。このインスタンスはデータベースに永続的に格納されます。ユーザーAPIはできるだけシンプルでなければなりません。たとえば、D Python記述子のようなメタプログラミング?
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
エンティティクラスには適切なメタクラスがあり、必要な接続が配線されます。ユーザーは、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
を使用している場合、私は異なる実装を試みたDへのORMを翻訳データベース
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
から人物のインスタンスを遅延ロードすることができます。シンプルbasetypesにとっては、テンプレートと統一された呼び出し構文と接続詞でのユーザー定義属性(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-memberをプロパティ関数で置き換えることですが、コンパイル時のメタプログラミングを使用してこれを行う方法はわかりません。それでどうやってこれをやるの?それとも、慣用的なやり方がありますか?
私はあなたが 'Person'をラップする' Deferred'テンプレートを作ることができたと思います。そこに 'get'関数を作成してロードし、' alias get this'を使って 'owner.get.xyz'の代わりに' owner.xyz'を書くことができます。 – weltensturm
私はそれを試みましたが、値を設定したいので、 'myCar.owner = new Owner(...);'と書く必要があります。だから私は取得し、設定するためにエイリアスを持っている必要があります。 –
テンプレートがクラスではなく構造体にインスタンス化されている場合、opAssignをオーバーライドできるはずですが、別名が構造体で機能するかどうかはわかりません。 – weltensturm