Einzelnen Beitrag anzeigen

Benutzerbild von DeepCopy
DeepCopy

Registriert seit: 5. Aug 2008
Ort: Gießen
21 Beiträge
 
Lazarus
 
#6

Re: Reihenfolge beim Laden von Properties verändern

  Alt 24. Okt 2008, 17:47
Hallo an alle,

whow - eine Menge Antworten - vielen Dank an alle die sich die Mühe gemacht haben, es war noch lang gestern Nacht ,d.h. etwas verspätet meine Antwort.

Also der Reihe nach:

@bernau
Die alphabetische Reihenfolge habe ich mehrfach getestet und es hat keinen Einfluss auf die Reihenfolge der Speicherung, aber mal ganz ehrlich, wer will denn schon in der JVCL eine Komponente benutzen die dem Benutzer im Objektmanager ein aPop1:Bool und bProp2:Bool anbietet.

@sirius
Ich habe neue Test-Poperties erstellt und hinzugefügt und wieder gelöscht, den Properties keine default Eigenschaft mitgegeben, sowie die Eigenschaften im Objektinspektor geändert,das Formular gespeichert, den Inhalt mit einem Editor überprüft und Debug-BrakePoints gesetzt die auch Angesprungen wurden und die erwarteten Werte hatten, das sollte das Einbinden absolut sicherstellen. -> Ergebnis die Reihenfolge beim Speichern in der *.dfm entspricht genau! der Reihenfolge der Klassendefinition im published Abschnitt.

@Roachford
Zitat von Roachford:
Die Reihenfolge ist nicht steuerbar. Wenn du abhängige Eigenschaften hast, dann führe die Prüfung in den einzelnen Settern nur durch, wenn nicht csLoading im ComponentState ist. Dadurch werden sie geprüft beim Setzen und haben somit immer einen gültigen Wert beim Speichern. Somit ist alles was aus der DFM geladen wird gültig und muss nicht geprüft werden.
Sorry das verstehe ich nicht!
csLoading ist Flag das anzeigt das die Komponente geladen wird, entweder aus einer Datei oder einem Stream, aber genau das ist der Zeitpunkt an dem der entsprechende Wert eingetragen werden soll.

Zu der Load Methode die ausgeführt wird, NACHDEM alle Properties geladen und csLoading aus dem ComponentState entfernt werden wird, konnte ich mich noch nicht durchringen, aber Danke für Deinen Hinweis.

@dataspider
Ja du hast Recht das Beispiel war sehr einfach, hier jetzt ein Praxisnahes:

Problemstellung: Ich habe eine CommandoProzessor Komponente geschrieben die Befehle vom Benutzer entgegen nehmen soll, direkt und
ohne Aufruf von cmd.exe /C... , diese Komponente funktioniert auch einwandfrei, jetzt bin ich auf den Gedanken gekommen das man einen TCustomMemo Nachfahren also TJvMemo und TMemo der Komponente zuweisen kann. Die Prozessor-Komponente übernimmt das Einstellen des Oberflächen-Designs des Memos als auch das Senden des PipeOutput's an das Memo, und hier kommt es auf die Reihenfolge an. Wenn die CommandProzessor Komponente auf der Oberfläche der IDE platziert wird soll der CommandProzessor natürlich noch nicht gestartet werden. Das soll nur möglich sein wenn eine TCustomMemo der Komponente zugewiesen ist. Dafür habe ich einen Property-Schalter AutoRunShell eingefügt , bei dem der Benutzer entscheiden kann, ob der CommandProzessor gleich nach dem Start des Programms gestartet wird und PipeOutput-Daten an das Memo gesendet werden.

Das Problem ist das der PipeOutput in einem Dispatcher-Thread untergebracht werden muss, da das OutputPipe Read-Ereignis solange blockiert wird bis Daten im Pipe vorliegen und dies erfordert die Übergabe der Memo-Komponente in der Create-Anweisung des TThread-Nachfahren, aber dies muss aber auch direkt nachdem der CommandProzessor gestartet ist geschehen, damit die InputPipe (evtl.) nicht blockiert oder Daten verloren gehen.

So also wenn jetzt das Programm startet wird im Setter der AutoRunShell geprüft ob eine TCustomMemo Komponente zugewiesen ist, und eine entsprechende Run() prozedur aufgerufen, die die Interna steuert, das ist alles.

Ein stark vereinfachtes Code-Beispiel des Modells:
Delphi-Quellcode:
type
  TCommandShell = class TComponent
    private
      FShellMemo: TCusomMemo;
      FAutoRunShell: Boolean;
      procedure SetAutoRunShell(Value: Boolean);
      procedure SetShellMemo(Value: TCustomMemo);
    protected
      procedure Run(); // macht die Arbeit -> Prozess starten, Thread starten usw.
    published

    // die ShellMemo, extra VOR der AutoRunShell platziert
    property ShellMemo: TCustomMemo
      read FShellMemo
      write SetShellMemo

     // ruft bei Bedarf die Run property auf
     property AutoRunShell:Boolean
       read FAutoRunShell
       write SetAutoRunShell;
end

procedure TCommandShell.SetShellMemo(Value: TCustomMemo); // dieser Setter sollte zuerst aufgerufen werden
                                                                                                      // er wird aber immer NACH allen einfachen Datentypen aufgerufen
begin
   FShellMemo := Value;
end;

procedure TCommandShell.AutoRunShell(Value: Boolean); // dieser Setter (und alle anderen einfachen Properties)
                                                                                           // wird IMMER vorher aufgerufen,
                                                                                           // egal wie ich es in der Klassendefnition angebe
begin
  FAutoRunShell := Value;
  if ( Assigned( FShellMemo ) AND FAutoShellRun ) then // <- Hier ist das Problem... ,FShellMemo wurde noch nicht zugewiesen
     Run(); // die Procedure die die Arbeit machen sollte
end;
So was ich noch rausgefunden habe:
Was doch funktioniert ist wenn man die Reihenfolge in der Klassedefinition ändert UND wenn es sich dabei um einfache (int,bool,float) und selbstdefnierte Datentypen (type pocedure TEventHandler of Object u.ä. handelt, dann ist die Reihenfolge steuerbar. Also mein Beispiel (von Post#1) Prop2 vor Prop1 zu definieren funktioniert, dies wie gesagt nur mit einfachen und selbstdefinierten Typen. Sobald etwas vom Typ Object und im speziellen TComponent ist funktioniert es nicht.

Dank an alle die sich die Zeit nehmen und genommen haben.
Andreas
Gruß Andreas
---------------------------------------------------
Sic Luceat Lux (so lasse das Licht erstrahlen)
- ich kam sah und wusste nichts -
  Mit Zitat antworten Zitat