AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Registrieren von Klassen

Ein Thema von barnti · begonnen am 10. Nov 2004 · letzter Beitrag vom 11. Nov 2004
Antwort Antwort
Seite 2 von 3     12 3      
barnti

Registriert seit: 15. Aug 2003
Ort: Mal hier mal da...
689 Beiträge
 
Delphi 7 Enterprise
 
#11

Re: Registrieren von Klassen

  Alt 11. Nov 2004, 10:20
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?
Gruß,

Barnti
  Mit Zitat antworten Zitat
choose

Registriert seit: 2. Nov 2003
Ort: Bei Kiel, SH
729 Beiträge
 
Delphi 2006 Architect
 
#12

Re: Registrieren von Klassen

  Alt 11. Nov 2004, 10:40
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.
gruß, choose
  Mit Zitat antworten Zitat
barnti

Registriert seit: 15. Aug 2003
Ort: Mal hier mal da...
689 Beiträge
 
Delphi 7 Enterprise
 
#13

Re: Registrieren von Klassen

  Alt 11. Nov 2004, 10:59
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...
Gruß,

Barnti
  Mit Zitat antworten Zitat
choose

Registriert seit: 2. Nov 2003
Ort: Bei Kiel, SH
729 Beiträge
 
Delphi 2006 Architect
 
#14

Re: Registrieren von Klassen

  Alt 11. Nov 2004, 11:20
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.
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
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.)
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...
gruß, choose
  Mit Zitat antworten Zitat
barnti

Registriert seit: 15. Aug 2003
Ort: Mal hier mal da...
689 Beiträge
 
Delphi 7 Enterprise
 
#15

Re: Registrieren von Klassen

  Alt 11. Nov 2004, 11:42
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.
Gruß,

Barnti
  Mit Zitat antworten Zitat
choose

Registriert seit: 2. Nov 2003
Ort: Bei Kiel, SH
729 Beiträge
 
Delphi 2006 Architect
 
#16

Re: Registrieren von Klassen

  Alt 11. Nov 2004, 11:54
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.
gruß, choose
  Mit Zitat antworten Zitat
barnti

Registriert seit: 15. Aug 2003
Ort: Mal hier mal da...
689 Beiträge
 
Delphi 7 Enterprise
 
#17

Re: Registrieren von Klassen

  Alt 11. Nov 2004, 12:04
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?!
Gruß,

Barnti
  Mit Zitat antworten Zitat
choose

Registriert seit: 2. Nov 2003
Ort: Bei Kiel, SH
729 Beiträge
 
Delphi 2006 Architect
 
#18

Re: Registrieren von Klassen

  Alt 11. Nov 2004, 12:14
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?
gruß, choose
  Mit Zitat antworten Zitat
barnti

Registriert seit: 15. Aug 2003
Ort: Mal hier mal da...
689 Beiträge
 
Delphi 7 Enterprise
 
#19

Re: Registrieren von Klassen

  Alt 11. Nov 2004, 12:21
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?!
Gruß,

Barnti
  Mit Zitat antworten Zitat
choose

Registriert seit: 2. Nov 2003
Ort: Bei Kiel, SH
729 Beiträge
 
Delphi 2006 Architect
 
#20

Re: Registrieren von Klassen

  Alt 11. Nov 2004, 12:41
Registriere Fabriken als Objekte (keine Klassen) innerhalb Deiner Registratur und geben ihnen bei der Ereuzgung die erforderlichen Parameter mit.
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
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?
gruß, choose
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 3     12 3      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:25 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