Einzelnen Beitrag anzeigen

Benutzerbild von s.h.a.r.k
s.h.a.r.k

Registriert seit: 26. Mai 2004
3.159 Beiträge
 
#12

AW: Rätselhaftes Konstrukt in Unit Dialogs

  Alt 30. Jan 2012, 10:04
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)

Geändert von s.h.a.r.k (30. Jan 2012 um 10:14 Uhr)
  Mit Zitat antworten Zitat