Datensätze können RTTI haben, aber nur wenn mindestens ein Referenzfeld (wie String oder Interface) vorhanden ist. Und diese Rekord RTTI ist sehr begrenzt, also wird es dir nicht weiter helfen.
Unter Delphi Live wurde gezeigt, dass RTTI in Delphi 2010 stark erweitert wird, so dass es möglicherweise auch RTTI-Datensätze erweitert hat.
Ich schlage vor, dass Sie eine Klasse von TComponent ableiten und verwenden Sie den integrierten Streaming-Mechanismus, oder verwenden RTTI, um es zu/von einer INI-Datei zu erhalten. Viel einfacher!
--jeroen
Edit: Beispiel
Zuerst wird die Komponente:
unit IntegerValueComponentUnit;
interface
uses
Classes;
type
TCustomIntegerValueComponent = class(TComponent)
strict private
FIntegerValue: Integer;
strict protected
function GetIntegerValue: Integer; virtual;
procedure SetIntegerValue(const Value: Integer); virtual;
public
property IntegerValue: Integer read GetIntegerValue write SetIntegerValue;
end;
TIntegerValueComponent = class(TCustomIntegerValueComponent)
published
property IntegerValue;
end;
implementation
function TCustomIntegerValueComponent.GetIntegerValue: Integer;
begin
Result := FIntegerValue;
end;
procedure TCustomIntegerValueComponent.SetIntegerValue(const Value: Integer);
begin
FIntegerValue := Value;
end;
end.
Dann wird die resultierende DFM-Datei:
object TIntegerValueComponent
IntegerValue = 33
end
Das DFM-Datei ziemlich einfach zu bearbeiten Wie bei INI-Dateien können Sie Fehler machen, daher ist es nicht empfehlenswert, sie von gelegentlichen Benutzern zu bearbeiten.
Sie benötigen diese Einheit, um loszulegen, das grundlegende Streaming zu/von Streams und die Umwandlung des Binärformats in das Textformat (wenn der Speicher mir recht tut, ist das Textformat seit Delphi 5 der Standard) wie es viel einfacher zu lesen ist).
unit ComponentDfmUnit;
interface
uses
Classes, IntegerValueComponentUnit;
type
TComponentDfm = class
public
class function FromDfm(const Dfm: string): TComponent; static;
class function GetDfm(const Component: TComponent): string; static;
class function LoadFromDfm(const FileName: string): TComponent; static;
class procedure SaveToDfm(const Component: TComponent; const FileName: string); static;
end;
implementation
class function TComponentDfm.FromDfm(const Dfm: string): TComponent;
var
MemoryStream: TMemoryStream;
StringStream: TStringStream;
begin
MemoryStream := TMemoryStream.Create;
try
StringStream := TStringStream.Create(Dfm);
try
ObjectTextToBinary(StringStream, MemoryStream);
MemoryStream.Seek(0, soFromBeginning);
Result := MemoryStream.ReadComponent(nil);
finally
StringStream.Free;
end;
finally
MemoryStream.Free;
end;
end;
class function TComponentDfm.GetDfm(const Component: TComponent): string;
var
MemoryStream: TMemoryStream;
StringStream: TStringStream;
begin
MemoryStream := TMemoryStream.Create;
try
MemoryStream.WriteComponent(Component);
StringStream := TStringStream.Create('');
try
MemoryStream.Seek(0, soFromBeginning);
ObjectBinaryToText(MemoryStream, StringStream);
Result := StringStream.DataString;
finally
StringStream.Free;
end;
finally
MemoryStream.Free;
end;
end;
class function TComponentDfm.LoadFromDfm(const FileName: string): TComponent;
var
DfmStrings: TStrings;
begin
DfmStrings := TStringList.Create;
try
DfmStrings.LoadFromFile(FileName);
Result := TComponentDfm.FromDfm(DfmStrings.Text);
finally
DfmStrings.Free;
end;
end;
class procedure TComponentDfm.SaveToDfm(const Component: TComponent; const FileName: string);
var
DfmStrings: TStrings;
begin
DfmStrings := TStringList.Create;
try
DfmStrings.Text := TComponentDfm.GetDfm(Component);
DfmStrings.SaveToFile(FileName);
finally
DfmStrings.Free;
end;
end;
end.
Und dann sollte dieses Beispiel arbeiten (zunächst den Formularcode, dann ist die Form DFM): Die wichtigste Zeile ist Register (TIntegerValueComponent);, wie es leicht zu vergessen ist. Der Rest des Codes ist ziemlich geradlinig.
Als Bonus sehen Sie auch, wie Sie eine Komponente in die Zwischenablage kopieren und wieder einfügen können. Es streamt zu/aus der Zwischenablage im Binärformat.
const
FileName = 'IntegerValue.dfm';
procedure TStreamingDemoForm.ButtonEnabledTimerTimer(Sender: TObject);
begin
SaveButton.Enabled := SaveStyleRadioGroup.ItemIndex <> -1;
LoadButton.Enabled := SaveButton.Enabled;
if SaveStyleRadioGroup.ItemIndex = 0 then
LoadButton.Enabled := FileExists(FileName);
if SaveStyleRadioGroup.ItemIndex = 1 then
LoadButton.Enabled := Clipbrd.Clipboard.HasFormat(CF_COMPONENT);
end;
procedure TStreamingDemoForm.LoadButtonClick(Sender: TObject);
var
IntegerValueComponent: TIntegerValueComponent;
begin
IntegerValueComponent := nil;
if SaveStyleRadioGroup.ItemIndex = 0 then
IntegerValueComponent := LoadUsingFileStream()
else
IntegerValueComponent := LoadUsingClipboard();
try
if Assigned(IntegerValueComponent) then
Log('Loaded: %d', [IntegerValueComponent.IntegerValue])
else
Log('nil during Load');
finally
IntegerValueComponent.Free;
end;
end;
function TStreamingDemoForm.LoadUsingClipboard: TIntegerValueComponent;
var
Component: TComponent;
begin
Result := nil;
RegisterClass(TIntegerValueComponent);
Component := Clipboard.GetComponent(nil, nil);
if Assigned(Component) then
if Component is TIntegerValueComponent then
Result := TIntegerValueComponent(Component);
end;
function TStreamingDemoForm.LoadUsingFileStream: TIntegerValueComponent;
var
Component: TComponent;
begin
Result := nil;
RegisterClass(TIntegerValueComponent);
Component := TComponentDfm.LoadFromDfm(FileName);
if Assigned(Component) then
if Component is TIntegerValueComponent then
Result := TIntegerValueComponent(Component);
end;
procedure TStreamingDemoForm.Log(const Line: string);
begin
LogMemo.Lines.Add(Line);
end;
function TStreamingDemoForm.Log(const Mask: string; const Args: array of const): string;
begin
Log(Format(Mask, Args));
end;
procedure TStreamingDemoForm.SaveButtonClick(Sender: TObject);
var
IntegerValueComponent: TIntegerValueComponent;
begin
IntegerValueComponent := TIntegerValueComponent.Create(nil);
try
IntegerValueComponent.IntegerValue := ValueToSaveSpinEdit.Value;
if SaveStyleRadioGroup.ItemIndex = 0 then
SaveUsingFileStream(IntegerValueComponent)
else
SaveUsingClipboard(IntegerValueComponent);
Log('Saved: %d', [IntegerValueComponent.IntegerValue])
finally
IntegerValueComponent.Free;
end;
end;
procedure TStreamingDemoForm.SaveUsingClipboard(IntegerValueComponent: TIntegerValueComponent);
begin
Clipboard.SetComponent(IntegerValueComponent);
end;
procedure TStreamingDemoForm.SaveUsingFileStream(IntegerValueComponent: TIntegerValueComponent);
begin
TComponentDfm.SaveToDfm(IntegerValueComponent, Filename);
end;
Schließlich wird die Form DFM:
object StreamingDemoForm: TStreamingDemoForm
Left = 0
Top = 0
Caption = 'StreamingDemoForm'
ClientHeight = 348
ClientWidth = 643
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
DesignSize = (
643
348)
PixelsPerInch = 96
TextHeight = 13
object ValueToSaveLabel: TLabel
Left = 14
Top = 8
Width = 65
Height = 13
Caption = '&Value to save'
FocusControl = ValueToSaveSpinEdit
end
object ValueToSaveSpinEdit: TSpinEdit
Left = 95
Top = 5
Width = 121
Height = 22
MaxValue = 0
MinValue = 0
TabOrder = 0
Value = 0
end
object SaveButton: TButton
Left = 14
Top = 33
Width = 75
Height = 25
Caption = '&Save'
TabOrder = 1
OnClick = SaveButtonClick
end
object LoadButton: TButton
Left = 14
Top = 64
Width = 75
Height = 25
Caption = '&Load'
TabOrder = 2
OnClick = LoadButtonClick
end
object LogMemo: TMemo
Left = 14
Top = 95
Width = 621
Height = 245
Anchors = [akLeft, akTop, akRight, akBottom]
Lines.Strings = (
'LogMemo')
TabOrder = 3
end
object SaveStyleRadioGroup: TRadioGroup
Left = 95
Top = 30
Width = 121
Height = 59
Caption = 'Save st&yle'
Items.Strings = (
'Value.dfm'
'Clipboard')
TabOrder = 4
end
object ButtonEnabledTimer: TTimer
Interval = 100
OnTimer = ButtonEnabledTimerTimer
Left = 270
Top = 6
end
end
posted ein Beispiel für das Erhalten der DFM-Dateien aus; werde das in Kürze auf meinem Blog posten. –
Sie können auch den akzeptierten Kommentar für diese Frage ansehen: http://stackoverflow.com/questions/1293504/what-is-the-best-way-to-serialize-delphi-application-configuration zeigt es Ihnen wie um das RTTI-Zeug selbst zu machen. –