Beispiel für die Nutzung bei uns:
Per Attribut wird festgelegt welche
XML-Knoten oder Datenbankeinträge zu den Feldern der Klasse gehören. Danach kann man die einfach an eine Funktion übergeben, die dann die Daten liest oder schreibt. Benutzen tun wir das z.B. bei Einstellungsklassen. Auf diese Weise müssen die Einstellungsklassen nichts über die Datenstrukturen wissen, in denen die Daten liegen.
Mache ich genauso - als hätten wir voneinander abgeschrieben
"Great minds think alike!"
Ich verklage euch -- ihr habt mein Patent 0815 verletzt
@Luckie: Wie scheinbar auch andere, handhabe ich das Mapping von Datenbank-Tabellen auf Objekte via Attribute. Beispiel:
Delphi-Quellcode:
// Tablle Blub:
// Spalte1
// Spalte2
// Spalte3
TModel = class abstract
public
// Diese Methode analysiert die Klasse und lädt aus der zugewiesenen
// Tabelle den nötigen Datensatz
procedure Load(const PrimaryKey: Integer); virtual;
end;
// Dazu gehörige Klasse
[TTableAttribute('Blub')] // Zuweisung einer Tabelle
TBlubModel = class(TModel)
private
[TTableColumnAttribute('Spalte1')]
FValue1: String;
[TTableColumnAttribute('Spalte1')]
FValue2: Integer;
[TTableColumnAttribute('Spalte1')]
FXyz: Variant;
end;
So könnte das ganze aussehen. Du brauchst somit quasi nur eine Load-Methode schreiben, die via (der neuen)
RTTI die abgeleitete Klasse TBlub analysiert und dann via PrimaryKey entsprechend lädt. Ist halt eine stark simplifizierte Version, aber ich denke, dass es schon aussagekräftig genug ist, bzw. das will ich mal hoffen
-- Edit: Alternativ könnte man auch einen "Loader" verwenden -- bin in Sache Patterns bzgl sowas leider nicht all zu fit. Hier mal mein Gedankengang:
Delphi-Quellcode:
// Es liegt hier selbige Tabelle, wie oben beschrieben, zugrunde!
// Basis-Model-Klasse
TModel =
class abstract
end;
TModelClass =
class of TModel;
// Konkretes Model
TBlubModel =
class(TModel)
private
[TTableColumnAttribute('
Spalte1')]
FValue1:
String;
[TTableColumnAttribute('
Spalte1')]
FValue2: Integer;
[TTableColumnAttribute('
Spalte1')]
FXyz: Variant;
end;
// Loader
TBaseModelFactory =
class
private
procedure AnalyseModel(Model: TModelClass);
public
function LoadByPk(Model: TModelClass; PrimaryKey: Integer): TModel;
function LoadByAttributes(Model: TModelClass; Attributes: TArray<TModelAttribute>): TArray<Model>;
function LoadbyWhereClause(Model: TModelClass; WhereClause:
String): TArray<TModel>;
end;
// Nutzung:
var
Model : TBlubModel;
Models : TArray<TBlubModel>;
begin
// Laden, über die Angabe des PK. Durch Angabe der klasse TBlubModel ist klar,
// auf welche Tabelle zugegriffen werden muss.
Model := TBaseModelFactory.LoadByPk(TBlubModel, 10);
// Laden via "Filter", d.h. über Angabe von Attributen, die dann entsprechend
// zu einer Where-Clause zusammengebaut werden.
// WICHTIG: Die Attribute sind hier nicht in korrekter Delphi-Syntax angegeben
// sondern entsprechend Pseudocode.
Models := TBaseModelFactory.LoadbyAttributes(TBlubModel, ['
Spalte1' = 10, '
Spalte2' = '
DP']);
// ... und dann noch via selbst modelliertem Where-Clause.
Models := TBaseModelFactory.LoadByWhereClause(TBlubModel, '
Spalte1 > 15 AND Spalte2 LIKE "%dp%"');
Für etwaige Fehler wird nicht gehaftet
habe gerade alles nur schnell aus dem Kopf runtergeschrieben, ohne es zu testen.
»Remember, the future maintainer is the person you should be writing code for, not the compiler.« (Nick Hodges)