Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Registrieren von Klassen (https://www.delphipraxis.net/33642-registrieren-von-klassen.html)

barnti 10. Nov 2004 15:08


Registrieren von Klassen
 
Hallo,
ich erzeuge in meiner Anwendung eine Klasse 'PDInterface'. In dieser möchte ich alle für meine Anwendung benötigten Klassen registrieren.
Ist das möglich?
Delphi-Quellcode:
unit PDInterface;
...

constructor TPDInterface.Create(Owner: TComponent); // Owner ist die Anwendung
var
  I: Integer;
  aClass: TPersistentClass;
  ClassName: String;
begin
  FApplication:= Owner;
  FDatabase:= TmyDatabase.Create(Owner);

  For i:=0 to Length(FClassArray) -1 do begin
    // Erzeugt Einträge aus den TabellenNamen der DB
    FClassArray[TClassIndex(i)]:= Database.FTableArray[i];
    // Ermittelt den aktuellen Tabellennamen und stellt ein'TPD' voran, welches dann den Namen
    // der Klasse ergibt
    ClassName:= 'TPD'+FClassArray[TClassIndex(i)];
    // Casten auf persistente zu registrierende Klasse
    aClass:= TPersistentClass(ClassName);
   // Versuch die aktuelle Klasse zu registrieren
   RegisterClass(aClass);
  end // for
end;
Leider schlägt das Registrieren mit eine Schutzverletzung fehl.

Kann jemand helfen?

mirage228 10. Nov 2004 15:28

Re: Registrieren von Klassen
 
Hi,

ist Deine Klasse von TPersistent abgeleitet bzw. ist die RTTI ({$M+}) dafür aktiviert?

mfG
mirage228

barnti 10. Nov 2004 15:32

Re: Registrieren von Klassen
 
Hi,

ja die zu registrierenden Klassen sind alle vom Typ TPersistent bzw. Unterklassen:

Delphi-Quellcode:
TPersistent
    |
TPDObject
    |
TPDMeineZuRegistrierendeKlasse

mirage228 10. Nov 2004 15:34

Re: Registrieren von Klassen
 
Hi,

dann versuch mal die Klasse im initialization Abschnitt der Unit zu registrieren.

mfG
mirage228

barnti 10. Nov 2004 15:36

Re: Registrieren von Klassen
 
Hi,

das war meine Frage: Kann ich das NUR dort?
Denn es müssen vorher erst einige Klassen zur Verfügung stehen, die die zu registrierenden Klassen ermitteln...!?

mirage228 10. Nov 2004 15:42

Re: Registrieren von Klassen
 
Zitat:

Zitat von barnti
Hi,

das war meine Frage: Kann ich das NUR dort?
Denn es müssen vorher erst einige Klassen zur Verfügung stehen, die die zu registrierenden Klassen ermitteln...!?

Hi,

Achso, das weiss ich nicht. Jedoch wurden bei den Programmen, die ich gesehen habe, die Klassen im initialization Abschnitt initialisiert.

Noch 2 Fragen:
ist aClass eventuell = nil ?
Hast Du schon versucht mit Debug DCUs zu kompilieren und auch in Delphi Sourcen mit reingetraced?

mfG
mirage228

maximov 10. Nov 2004 15:55

Re: Registrieren von Klassen
 
Delphi-Quellcode:
var...
  ClassName: String;
...
  aClass:= TPersistentClass(ClassName);
:shock: Du kannst nicht einfach einen String auf eine metaklasse casten :wink: ..abgesehen davon solltest du diese variable nicht ClassName nennen, da dies eine klassen-methode von TObject ist.

Du brauchst hier schon explizit die klasse. das was du da versuchst, geht auf keinen fall...und wenn es gehen würde, dann bräuchtest du die klasse ja nicht mehr registrieren.

Aber erzähl doch mal was du erreichen willst?

barnti 10. Nov 2004 18:57

Re: Registrieren von Klassen
 
Hallo,

ich möchte in die für meine Anwendung benötigten Klassen automatisch generieren. Dazu existiert für jede DB-Tabelle eine eigene Klasse. Bei der Initialisierung der Anwendung oder beim Erzeugen des Hauptformulars möchte ich die benötigten Klassen erzeugen. Möglichst über eine einzige Prozedur, die über ein Array der Tabellennamen iteriert.

Ich bin zur Zeit nicht an meinem Arbeitsplatz, so dass ich erst morgen wieder genauer auf das Problem eingehen kann...

barnti 11. Nov 2004 07:41

Re: Registrieren von Klassen
 
Hallo,

nun noch einaml zurück zum Thema. Ich möchte in einer Klasse alle für die Konfiguration erforderlichen Daten ablegen. Dazu gehören auch Prozeduren und Funktionen, die mir zur Laufzeit Konfigurationsarameter ermitteln. Hier mal etwas Code:
Delphi-Quellcode:
unit ConfigFile;

interface

uses
  SysUtils, Windows, Messages, Classes, Graphics, Controls,
  Forms, Dialogs;

type
  TConfigFile = class (TObject)

...

TPDObjectClass = class of TPersistent;

{ Hier müssen alle in der Datenbank enthaltenen Tabellen angegeben werden.
}
TClassIndex = (   
              {1}    Ansprechpartner,
              {2}    Auftrag,
              {3}    auftragstatus,
              {4}    ...
              {5}
              {6}   
              {7}   
              {8}   
              {9}   
              {10}   
              {11}   
              {12}   
              {13}   
              {14}   
              {15}   
              {16}   
              {17}   
              {18}   
              {19}   
              {20}   
              {21}   
              {22}   
              {23}   
              {24}   
              {25}   
              {26}   
              {27}   );

// Beinhaltet die Namen der Tabellen. Um mit einer Klasse zu Arbeiten, wird die
// entsprechende Klasse aus dem Array per Tabellenname oder per Index gesucht und ein 'TPD'
// vorangestellt, um den Namen der Klasse zu erhalten
TClassArray= array[Ansprechpartner..zustaendigkeit] of String;

procedure Register;

implementation
// Hier stehen statische Parameter
const
  C_DatabaseName = 'Name';
  C_Host        = 'Host';
...

//Das 'ClassArray' lade ich zur Laufzeit aus der DB (TableList):
 for i:=0 to TableList.Count-1 do
      ClassArray[TClassIndex(i)]:= List.Strings[i];

...

//Nun kann ich folgendes machen:
function TPDInterface.GetPDObject(Index: Integer): TPDObject;
var
  pdClass: TPDObjectClass;
begin
  pdClass:= findClass('TPD'+ClassArray[TClassIndex(index)]);
  //pdClass:= findClass('TPDAnsprechpartner');
  if FPDObjects[index]= NIL then FPDObjects[index]:= TPDObject.Create(Database);
  result:= FPDObjects[index];
Dazu müssen die Klassen allerdings registriert sein:
Delphi-Quellcode:
initialization
 RegisterClasses([TPDAnsprechpartner,TPDAuftrag, TPDAuftragstatus,...]);
Da ich aber erst zur Laufzeit auf die Config-Klasse zugreifen kann, muss ich das Registrieren also an einer anderen Stelle tun als im Initialization-Teil.

Ich dachte also das könnte ich auch beim Erzeugen meines Hauptformulars tun:
Delphi-Quellcode:
unit main
...
constructor TForm1.FormCreate(Sender: TObject);
var
  I: Integer;
  aClass: TPDObjectClass;
  ClassName: String;
begin
  FApplication:= Owner;
  // Hier werden alle Parameter des ConfigFiles geladen und die TabellenNamen der DB ermittelt
  FDatabase:= TmyDatabase.Create(Owner);

  For i:=0 to Length(FClassArray) -1 do begin
    FClassArray[TClassIndex(i)]:= Database.FTableArray[i];
    ClassName:= 'TPD'+FClassArray[TClassIndex(i)];
    aClass:= TPDObjectClass(ClassName);
    RegisterClass(aClass);
  end // for
end;
Mein Hauptanliegen ist es alle Konfigurationsparameter in einer eigenen Klasse zu halten (ConfigFile).
Kann jemand dazu Stellung nehmen? Kann jemand helfen?

choose 11. Nov 2004 08:55

Re: Registrieren von Klassen
 
Hallo barnti,

klingt nach einem interessanten Vorhaben, dass ich in Delphi (außerhalb der VCL) in veröffentlichten Projekten mit Quelltext bisher nur bei Bei Google suchenLog4D sehen konnte.
Generell habe ich zur Lösung ähnlicher Probleme häufig diesen Ansatz gesehen:
  1. Registratur aller Klassen im Initialization-Abschnitt der jeweiligen Unit. Es ist nicht erforderlich, das in einer zentralen Unit zu tun, sondern jede Unit kann die zu registrierenden Klassen in ihrer Implementierungsunit registrieren.
  2. Laden der Konfiguration (dem Mapping), die im Wesentlichen einen Schlüssel (hier: Dein Tabellenname) auf eine Klasse abbildet (hier: ein Klassenname). Ist sie geladen, sind Ausdrücke der Art denkbar
    Delphi-Quellcode:
    myClassName := Configuration.GetClassNameFromKey(myTableName);
    Dieser Schritt könnte zB in Deinem Hauptformular geschehen und es spricht nichts dageben, unterschiedliche Konfigurationen für unterschiedliche Formualare, Abläufe oä vorzuhalten.
  3. Erzeugung der Benötigten Klasse mithilfe der Registratur in der Art
    Delphi-Quellcode:
    with Registration do
      myClass := GetClassFromName(Configuration.GetClassNameFromKey(myTableName);
    myObject := myClass.Create(myContext);

Vielleicht solltest Du Dir noch einmal das Bei Google suchenEntwurfsmuster abstrakte Fabrik (Bei Google suchenabstract factory pattern) ansehen, und in Erwägung ziehen, eine Menge von Fabriken zu konfigurieren, was den Ansatz wesentlich flexibler macht...

barnti 11. Nov 2004 09:20

Re: Registrieren von Klassen
 
Hallo Choose,

danke für Deine Antwort! Ich arbeite bereits mit Entwurfsmustern. Die Abstrakte Fabrik und das Singleton-Muster sind bereits verbaut. Ich habe dies lediglich wegen der Übersichtlichkeit weggelassen.
Der Punkt ist:
Wenn ich die Klassen in meiner Unit 'Main' registriere, muss ich bei der Erstellung einer neuen Tabelle in der DB und der Erstellung der zugehörigen Klasse für die Behandlung an zwei Stellen Veränderungen vornehmen:
ConfigFile: Tabellenname als ArrayIndex hinzufügen
UND
In der Unit 'Main':
Zu registrierende Klasse im Initialization-Abschnitt angeben.

Mein Gedanke war es alles an einer Stelle(in einer Unit) vorzuhalten. Ob das in der Registrierung geschieht oder in einer Klasse sollte nicht entscheidend sein.

So wie ich dich verstehe sollte(MUSS) das Registrieren der Klassen in den Initialization-Abschnitt.
Kommt in der DB eine neue Tabelle hinzu, dann ist demnach folgendes zu tun:

1. Klasse für die Tabelle Implementieren
2. Tabellenindex in das ClassArray aufnehmen
3. Klasse im Initialization-Teil registrieren


Dann kann ich auch mit dem folgenden Konstrukt arbeiten
Delphi-Quellcode:
function TPDInterface.GetPDObject(Index: Integer): TPDObject;
var
  pdClass: TPDObjectClass;
begin
  // Klasse über Idex des Arrays ansprechen(theoretisch geht dann auch der Name der Tabelle)
  pdClass:= findClass('TPD'+ClassArray[TClassIndex(index)]);
  //pdClass:= findClass('TPDAnsprechpartner');
  if FPDObjects[index]= NIL then FPDObjects[index]:= PDClass.Create(Database);
  result:= FPDObjects[index];
Ist das soweit richtig gedacht?

choose 11. Nov 2004 09:40

Re: Registrieren von Klassen
 
Der Ort der Registrierung ist im Wesentlichen egal, sie sollte lediglich chronoligisch gesehen vor der Verwendung stattfinden...

Mir ist der Sinn hinter dem ClassArray nicht ganz klar. In Deinem Kommentar schreibst Du, dass hier zu jeder Tabelle (Entität) eine geeignete Klasse registriert sein sollte, und hinterlegst stattdessen eine textuelle Bezeichnung, die der der Entität zu entsprechend scheint ("Ansprachpartner", "Auftrag", etc.). Dies ist nach meinem Empfinden eine redundante Information, weil sie bereits in Deinem Datenbankschema existiert, oder nicht?
Was spricht also dagegen, die Schemainformationen zu nutzen und die Bezeichnung Deiner Entität als Key für Dein Mapping zu verwenden. In der Configuration könnte nun hinterlegt werden, wie ein Schlüssel, zB "Ansprechpartner" auf einen Klassennamen, hier zB "TPDAnsprechpartner" abbilden soll. Falls Du in Deiner Konfiguration (zB in einer externen Datei) keine explizite Angabe machst, könnte dieses Mapping jedoch durch einfaches Konkatenieren geschehen, also etwa in der Art
Delphi-Quellcode:
function TConfiguration.GetClassNameFromKey(const AKey: string): string;
begin
  if KeyWasConfigured(AKey) then
     Result := GetValueFromKey(AKey)
  else
     Result := Format('%s%s%s', [FPrefix, FKey, FPostfix]);
end;
Existieren nun drei verschiedene geeignete Implementierungen für die Entität "Ansprechpartner", kann zur Laufzeit entschieden werden, ob die Klasse "TPDAnsprechpartner" oder eine andere durch ihren Klassennamen konfigurierte Klasse verwendet werden sollte.

Interessant ist, dass Du mithilfe des Datenbankschemas eine Prüfung durchführen kannst, die sicherstellt, dass bei einer Null-Konfiguration (ohne angepasstes Mapping) alle benötigten Klassen existieren (registriert worden sind), bzw beim Laden einer Konfiguration mit Anpassungen entsprechend verfährt und unter Ausgabe eines Hinweises für ggf nicht vorhandene Klassen auf den Null-Wert verfällt.

barnti 11. Nov 2004 09:59

Re: Registrieren von Klassen
 
Hallo Choose,

ist ich weiß nicht, ob ich alles verstanden habe.

Noch einmal zur Erklärung:

Für jede Tabelle in der DB soll eine Klasse existieren. Dafür muss beim 'Laden' der Anwendung folgendes geschehen:

1.Klassen registrieren: Stehen in Initialization-Teil

Das genügt für den Start der Anwendung. Möchte ich jetzt mit einer Tabelle arbeiten, so wird das in der Anwendung ausgelöst:
Der Benutzer wählt eine Tabelle mit Namen oder den Index der Tabelle und deren Inhalt in einem z.B. TDBGrid anzeigen zu lassen.

Dieses Laden der Tabelle sollte generisch geschehen. Dazu wird entweder der Index oder der Tabellenname benötigt:
Delphi-Quellcode:
function TPDInterface.GetPDObject(Index: Integer): TPDObject;
var
  pdClass: TPDObjectClass;
begin
  // Klasse über Idex des Arrays ansprechen(theoretisch geht dann auch der Name der Tabelle)
  pdClass:= findClass('TPD'+ClassArray[TClassIndex(index)]);
  //pdClass:= findClass('TPDAnsprechpartner');
  if FPDObjects[index]= NIL then FPDObjects[index]:= PDClass.Create(Database);
  result:= FPDObjects[index];
Um das zu ermöglichen sind die Tabellen in im Array 'ClassArray' mit dem Namen gespeichert. In der Funktion soll damit also ein Objekt vom Typ 'findClass('TPD'+ClassArray[TClassIndex(index)]);' erzeugt werden.
Deshalb das Array.
Ist das verständlich? Oder denke ich umständlich?

Ich will lediglich die Erzeugung generisch geschehen lassen... Das Mapping geschieht mit Hilfe des 'ClassArray'.
Das Datenbankschema lässt sich nicht einfach indiziert ansprechen deshalb das Array...

choose 11. Nov 2004 10:20

Re: Registrieren von Klassen
 
Der Benutzer öffnet eine Tabelle mit der Bezeichnung "Ansprechpartner" und Du möchtest daraufhin ein Objekt der geeigneten Klasse erzeugen. Hierzu könntest Du den Klassennamen mithilfe einer Konfiguration (Mapping) ermitteln, indem Du den Namen der Tabelle als Schlüssel übergibst.
Delphi-Quellcode:
myClassName := Configuration.GetClassNameFromKey('Ansprechpartner');
Im Normalfall (es wurde kein Spezielles Mapping hinterlegt) erzeugtt die Konfiguration den Klassennamen durch Aneinanderhängen von fest definierten Teilstrings. Der Inhalt von myClassName lautet in Deinem Fall also "TPDAnsprechpartner". Um nun ein Objekt erzeugen zu können, ist es notwendig, vom ermittelten Klassennamen auf die Klasse selbst zu schließen. Das Geschieht mithilfe Deiner Registratur (oder, falls Du RegisterClass verwendest mit FindClass) in der Art
Delphi-Quellcode:
myClass := Registration.GetClassFromName(myClassName);
Falls Du FindClass verwendest ist hier natürlich ein Cast auf die von Dir verwendete Klasse notwendig, um den passenden virtuellen(!) Konstruktur aufrufen zu können.
Anschließend erzeugst Du ein Exemplar der nun bekannten Klasse durch einen Aufruf des Konstruktors und übergiebst ihm alle notwendigen Parameter (zB Tabelle, Rechte, etc.)
Delphi-Quellcode:
Result := myClass.Create(myContext);
Das Erzeugen geschieht also generisch und das Mapping -so von Dir beschrieben- kann im Regelfall ebenfalls ohne weitere Anpassungen geschehen. Erst, wenn Klassen- und Tabellenname nicht länger gemäß des Musters übereinstimmen, ist es notwendig, die Konfiguration anzupassen, was zB einmalig im Konstruktor oder eine andere Zuweisungsform geschehen könnte.
Im Allgemeinen gilt jedoch: Kommt eine Tabelle hinzu, die mithilfe einer bereits verwendeten Klasse bearbeitet werden kann, braucht nur die Konfiguration angepasst werden oder -der Regelfall- kommt eine neuartige Tabelle hinzu, wird eine neue Klasse angelegt, in der Unit ihrer Implementierung registriert wird.

Dies ist lediglich eine Idee, die auf dem, was ich aus Deiner Aussage verstanden habe, fußt...

barnti 11. Nov 2004 10:42

Re: Registrieren von Klassen
 
Hi Choose,

ok das habe ich soweit geblickt. Um das Ganze noch einmal zu festigen:
Delphi-Quellcode:
TPersistent
     |
TPDObject // Allgemeine Klasse, die die gameinsamen Eigenschaften aufnimmt
     |
TPDAppObject // Klaase, die für diese Anwendung spezifische Eigenschaften beinhaltet
     |
TPDAnsprechpartner // Spezielle Eigenschaften und Methoden für die Behandlung einer speziellen Tabelle
Wenn ich jetzt in meiner Anwendung mit der Tabelle 'Ansprechpartner' arbeiten will, geschieht folgendes:
Delphi-Quellcode:
// Interface über das das Arbeiten mit einer Klasse veröffentlicht wird(Schnittstelle)
function TPDInterface.GetPDObject(Index: Integer): TPDObject;
var
  pdClass: TPDObjectClass;
begin                                  // ergibt 'Ansprechpartner'
  pdClass:= findClass('TPD'+ClassArray[TClassIndex(index)]);

  // Array das Objekte vom Typ 'TPDObject speichert'
  if FPDObjects[index]= NIL then FPDObjects[index]:= PDClass.Create(Database);
  result:= FPDObjects[index];
Das ist damit ein Problem. Wie der Objekthierarchie zu entnehmen ist, ist 'TPDAnsprechpartner' ein spezialisierteres Objekt. Wie Speichere ich meine Speziellen Objekte? So geht es nicht! Und das Erzeugen klappt so auch nicht.
Hier sollte ja letztendlich stehen:
Delphi-Quellcode:
function TPDInterface.GetPDObject(Index: Integer): TPDObject;
var
  pdClass: TPDObjectClass;
begin
  pdClass:= findClass('TPD'+ClassArray[TClassIndex(index)]);
                                                     // TPDAnsprechpartner.Create(Database);
  if FPDObjects[index]= NIL then FPDObjects[index]:= PDClass.Create(Database);
  result:= FPDObjects[index];
So klappt die generische Erzeugung nicht.

choose 11. Nov 2004 10:54

Re: Registrieren von Klassen
 
Der Signatur von FindClass ist zu entnehmen, dass der Rückgabewert vom Typ TPersistentClass. Du musst ihn deshalb auf den von Dir benötigten Casten (ähnlich wie es in Delphi bei Objekten in Ereignisbehandlungsroutinen gemacht wird, wenn statt Sender als TObject die Schnittstelle von TButton benötigt wird) oder eine eigene Registratur implementieren, damit Deine Lösung typsicher wird.

Delphi-Quellcode:
var
  myClass: TPDObjectClass;
begin
  myClass := TPDObjectClass(FindClass('TPDAnsprechpartner'));
nun kann der in TPDObjectClass eingeführte Konstruktor verwendet werden.

Achtung: Sollte der Konstruktor in einem Nachkommen von TPDObjectClass abermals überschrieben worden sein und ist er in TPDObjectClass nicht als virtuell markiert worden, wirst Du hier Probleme bekommen. Sieh Dir einmal den Ansatz von TComponent im Hinblick auf die Konstruktoren der Erben an, damit Du siehst, was ich meine.

barnti 11. Nov 2004 11:04

Re: Registrieren von Klassen
 
Hi Choose,

das ist richtig. Nur habe ich dann das folgende Problem:
Delphi-Quellcode:
unit PDInterface;
...
type
// Metaklassenvariable
TPDObjectClass = class of TPDObject;
TClassIndex = (Ansprechpartner,Auftrag,auftragstatus,benutzer,bereich,beschaedigung,config,
               container,dbdesigner4,dokument,foto,hafenplatz,kolli,Kunde,
               packliste,partie,partiestatus,partiekarte,pending,position,produktbeschreibung,
               produktgruppe,sql,unterpartie,userconfig,vertrag,zustaendigkeit);
TClassArray= array[Ansprechpartner..zustaendigkeit] of String;

  TPDInterface = class (TObject)
  private
    ClassArray: TClassArray;
    {{
    FDatabase is the state field of the Database property.
    }
    FDatabase: TmysqlDatabase;
    {{
    Field FPDObjects.
    }
    FPDObjects: array of TPDObject;

...
function TPDInterface.GetPDObject(Index: Integer): TPDObject;
var
  pdClass: TPDObjectClass;
begin
  // Zur Vereinfachung: Klasse TPDAnsprechpartner finden
  pdClass:= TPDObjectclass(findClass('TPDAnsprechpartner'));
 
  // Erzeugen eines Objektes der gefundenen (?) Klasse
  // Die spezielle Klasse erfordert aber den Parameter 'Name' zur Erzeugung?! Und nicht  
  //Database!? 
  PDClass.Create(Database);
  // Demnach müsste hier stehen
  // PDClass.Create('MeinName');
end;
Dies leht der Compiler aber ab!
Wo ist mein Fehler?!

choose 11. Nov 2004 11:14

Re: Registrieren von Klassen
 
Ein Konstruktor mit diese Signatur (String als einziger Parameter) scheint in TPDObject nicht eingeführt worden zu sein und kann daher auch nicht verwendet werden (so, wie Mathoden eines Erben nicht verwendet werden können, wenn Du eine Referenz vom Typ des Vorfahren verwendest).

Dies entspricht dem Problem mit dem nicht-veränderbaren Konstruktor meines vorherigen Postings und könnte ggf mit Hilfe des Musters Abstrakte Fabrik oder bem Besucher Muster gelöst werden.

Das Kernproblem: Einheitliche Verarbeitung trotz unbekannter Klasse.

Verstehe ich das richtig?

barnti 11. Nov 2004 11:21

Re: Registrieren von Klassen
 
Hi Choose,

genau das ist das Problem! Ich will ja die speziellen Objekte erzeugen. Die Vorfahren dienen nur zur Vorhaltung allgemeiner Methoden.
Allerdings weiß ich nicht wie ich das dann in eine Fabrikmethode bekomme!? Dort müsste ich dann ja nach dem übergebenen Parameter entscheiden welche Klasse zu erzeugen ist. In etwa:
Delphi-Quellcode:
function CreatePDObject(Index: Integer): TPDObject;
begin
  case index of
    0: TPDAnsprechpartner.Create('Name');
...
end;
Das ist ja dann nicht wirklich generisch.
Oder hattest Du da etwas anderes im Sinn, das mir entgangen ist?!

choose 11. Nov 2004 11:41

Re: Registrieren von Klassen
 
Registriere Fabriken als Objekte (keine Klassen) innerhalb Deiner Registratur und geben ihnen bei der Ereuzgung die erforderlichen Parameter mit.
Delphi-Quellcode:
myConfiguration.RegisterFactory('Ansprechpartner', TAnsprechpartnerFactory.Create('Name'));
Sie selbst wissen, gemäß des Musters, wie die späteren Exemplare (zB TPDAnpsprechpartner). Es werden nun nicht länger die Klassen des gewünschten Exemplars festgehalten und zurückgegeben sondern ein geeignetes Fabrik-Objekt. Um letztlich das erforderliche Exemplar zu erzeugen, genügt ein Aufruf der Form
Delphi-Quellcode:
Result := myFactory.CreateInstance;
Eine Alternative wäre, den Konstruktor der gemeinsamen Oberklasse mit einem generischen Parameter (seinerseits eine abstrakte Klasse) zu versehen.

Wie erlangst Du denn überhaupt die speziellen Daten, die zur Übergabe an den Konstruktor erforderlich sind im Augenblick der Erzeugung?

barnti 11. Nov 2004 11:50

Re: Registrieren von Klassen
 
Hi Choose,

Zitat:

Zitat von choose
Wie erlangst Du denn überhaupt die speziellen Daten, die zur Übergabe an den Konstruktor erforderlich sind im Augenblick der Erzeugung?

Das war nur ein Beispiel. Die Daten werde ich ebenfalls in der DB vorhalten. Das ist aber im Moment noch nicht so wichtig.

Entscheident ist, ich werde die Erzeugung der Objekte nur Vereinfachen können, indem ich der Abtrakten Fabrik den entprechenden Parameter für die Erzeugung mitgebe, wie von Dir dargetellt.
Ich denke damit habe ich erst einmal zu tun und damit ist mir auch erst einmal geholfen.
Solltest Du weitere Ideen, Anregungen oder Bmerkungen jeder Art haben, können wir hier gern weiterposten. Danke Dir!

maximov 11. Nov 2004 13:29

Re: Registrieren von Klassen
 
Hi Barnti, hi Choose :-D

kleine bemerkungen am rande:
Delphi-Quellcode:
TClassIndex = (Ansprechpartner,Auftrag,auftragstatus,benutzer,bereich,beschaedigung,config,
               container,dbdesigner4,dokument,foto,hafenplatz,kolli,Kunde,
               packliste,partie,partiestatus,partiekarte,pending,position,produktbeschreibung,
               produktgruppe,sql,unterpartie,userconfig,vertrag,zustaendigkeit);
TClassArray= array[Ansprechpartner..zustaendigkeit] of String;
Hier benutzt du zum definieren der array-grenzen eine range, die sowieso den gesammten bereich des enum-typs einschliesst. Dies kannst du auch so machen...
Delphi-Quellcode:
TClassArray= array[TClassIndex] of String;
...dann müsstest du nicht immer die array-deklaration anpassen. Darüber hinnaus frag ich mich, ob dieses array überhaupt von nöten ist? Denn man kann einen enum-wert auch leicht zu einem string auflösen. zB.:
Delphi-Quellcode:
uses typInfo;
...
function GetClassByClassIndex(const aClassIndex:TClassIndex):TPDObjectClass;
var clsName:strinf;
begin
  clsName := foramt('TPD%s',[getEnumName(TypeInfo(TClassIndex), integer(aClassIndex))]);
  result := findClass(clsName);
end;

function CreateObjectByClassIndex(const aClassIndex:TClassIndex):TPDObject;
var aClass:TPDObjectClass
begin
  aClass := GetClassByClassIndex(aClassIndex);
  if assigned(aClass) then
    result := aClass.create(<standard_params>)
  else
    result := nil;
end
Da eine metaklasse ja auch eine primitive fabrik ist, wäre das möglicherweise schon ausreichend. Hab aber dein problem auch nicht ganz kapiert. Für abstraktere lösungen bietet sich natürlich Choosens lösung an, oder eine kombination.

Vielleicht nütz das dir ja was. Und ich frag mich warum du als index ansonsten einen integer benutzt, der ja alles andere als eindeutig sein kann, bzw verrutschen könnte?


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:45 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz