Autor |
Beitrag |
Thjostalf
      
Beiträge: 21
Win2k, WinXP
D3 Prof, D4 Prof, Turbo Delphi Prof
|
Verfasst: Mi 12.04.06 10:55
Hallo,
ich versuche mich gerade an der Umsetzung des folgenden Problems:
Ich habe eine Superklasse, die Methoden zum Laden uns Speichern bereitstellt. Davon abgeleitet gibt es momentan eine, zukünftig (wenn's denn klappt) mehrere Tochterklassen, die hauptsächlich als Datencontainer fungieren sollen, sprich einfache Datentypen aufnehmen sollen.
Jetzt wollte ich nicht in jeder Tochterklasse eine Methode "save" anlegen müssen, sondern ich will, daß das Speichern und Laden primär über die Superklasse läuft.
Leider springt mir immer eine Exception entgegen, wenn ich die published Properties der Subklasse ermitteln möchte. Nehme ich statt dessen irgendein Objekt einer anderen Klasse, z.B. TButton, funktioniert's.
Weiß jemand einen Rat?
Vereinfacht mein Sourcecode:
Superklasse
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39:
| unit uParameterSet;
interface
type TParameterSet = class(TObject) private public procedure Save; end;
implementation
uses Classes, Windows, SysUtils, Controls, Forms, TypInfo, Dialogs, ApplicationWindow, StdCtrls;
procedure TParameterSet.Save(); var plList: tPropList; iTest: integer; Obj: TButton; begin
Obj:= TButton.Create(nil); MessageDlg(Self.ClassName, mtInformation, [mbOK], 0); iTest:= GetPropList(PTypeInfo(Self.ClassInfo), [tkUnknown, tkVariant, tkInteger, tkFloat, tkString, tkWString, tkLString, tkChar, tkWChar, tkEnumeration, tkSet, tkClass, tkMethod, tkArray, tkRecord, tkInterface], @plList);
MessageDlg(IntToStr(iTest), mtInformation, [mbOK], 0);
Obj.Free(); end;
end. |
Tochterklasse
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38:
| unit uParmSetTest;
interface
uses uParameterSet;
type TParmSetTest = class(TParameterSet) private PTest: string; function GetTest: string; procedure SetTest(aString: string); published property Test: string read GetTest write SetTest; end;
implementation
uses Forms, SysUtils;
function TParmSetTest.GetTest(): string; begin Result:= PTest; end;
procedure TParmSetTest.SetTest(aString: string); begin PTest:= aString; end; end; |
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Mi 12.04.06 11:09
Leite deine Hauptklasse von TPersistent ab und deklariere alle zu speichernden Werte als published-Properties. Danach kannst Du die Daten über TStream.WriteComponent bzw. TStream.Readcomponent (IIRC) schreiben bzw. lesen.
Anzumerken sei an dieser Stelle auch, dass Delphi für jede Klasse mit Compiler-Status {$H+} Laufzeittyp-Informationen generiert, die man für diesen Zweck auswerten kann (siehe TypeInfo). Der Zugriff auf diese und deren Verarbeitung ist aber das Grauen schlechthin für ungeübte User ...
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
Thjostalf 
      
Beiträge: 21
Win2k, WinXP
D3 Prof, D4 Prof, Turbo Delphi Prof
|
Verfasst: Mo 17.04.06 19:44
Titel: Die Lösung
Hallo,
ich habe für mich eine Lösung gefunden. Für den Fall, daß noch jemand den gleichen Gedanken verfolgen sollte, folgt hier der Code der Basisklasse...
Die Unit uRegistryTools und die daraus verwendeten Klassenmethoden kapseln nur etwas den Registry-Zugriff, so daß ein vereinfachter Zugriff auf HKCU\Software\Company\Application besteht. Die benötigten Informationen werden aus den Programmeigenschaften ermittelt.
Die 3 Stellen müßte man also noch etwas umschreiben oder bei mir den entsprechenden Code erfragen.
Grüße - und danke für TPersistent, Marian
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126:
|
unit uParameterSet;
interface
uses Classes;
type TParameterSet = class(TPersistent) public procedure LoadFromUserRegistry; procedure SaveToUserRegistry; end;
implementation
uses SysUtils, TypInfo, uRegistryTools;
procedure TParameterSet.LoadFromUserRegistry(); var iProp: Integer; PropCount: Integer; PropList: PPropList; PropInfo: PPropInfo; PropName: string; PTInfo: PTypeInfo; PTData: PTypeData; vValue: Variant; begin PTInfo:= Self.ClassInfo; PTData:= GetTypeData(PTInfo); GetMem(PropList, PTData^.PropCount * SizeOf(PPropInfo));
try TRegistryTools.OpenRegistry(); PropCount:= GetPropList(PTInfo, [tkFloat, tkInteger, tkString, tkLString, tkWString ], PropList);
for iProp:= 0 to PropCount - 1 do begin PropName:= PropList^[iProp]^.Name; PropInfo:= GetPropInfo(PTInfo, PropName);
if PropInfo <> nil then begin vValue:= TRegistryTools.ReadRegistryStringEntry(PropName); case PropInfo^.PropType^.Kind of tkFloat: SetFloatProp(Self, PropInfo, VarAsType(vValue, varDouble)); tkInteger: SetOrdProp(Self, PropInfo, VarAsType(vValue, varInteger)); tkString, tkLString, tkWString: SetStrProp(Self, PropInfo, VarAsType(vValue, varString)); end; end; end; finally FreeMem(PropList, PTData^.PropCount * SizeOf(PPropInfo)); TRegistryTools.CloseRegistry(); end; end;
procedure TParameterSet.SaveToUserRegistry(); var iProp: Integer; PropCount: Integer; PropList: PPropList; PropInfo: PPropInfo; PropName: string; PTInfo: PTypeInfo; PTData: PTypeData; vValue: Variant; begin PTInfo:= Self.ClassInfo; PTData:= GetTypeData(PTInfo); GetMem(PropList, PTData^.PropCount * SizeOf(PPropInfo));
try TRegistryTools.OpenRegistry(); PropCount:= GetPropList(PTInfo, [tkFloat, tkInteger, tkString, tkLString, tkWString ], PropList);
for iProp:= 0 to PropCount - 1 do begin PropName:= PropList^[iProp]^.Name; PropInfo:= GetPropInfo(PTInfo, PropName);
if PropInfo <> nil then begin case PropInfo^.PropType^.Kind of tkFloat: vValue:= GetFloatProp(Self, PropInfo); tkInteger: vValue:= GetOrdProp(Self, PropInfo); tkString, tkLString, tkWString: vValue:= GetStrProp(Self, PropInfo); end; TRegistryTools.WriteRegistryStringEntry(PropName, VarAsType(vValue, varString)); end; end; finally FreeMem(PropList, PTData^.PropCount * SizeOf(PPropInfo)); TRegistryTools.CloseRegistry(); end; end;
end. |
|
|
|