レコードにはRTTIを含めることができますが、少なくとも1つのリファレンスカウントフィールド(文字列またはインターフェイスなど)がある場合に限ります。そしてその記録RTTIは非常に限られているので、あなたを助けるものではありません。
Delphi LiveにDelphi 2010でRTTIが大幅に拡張される予定であることから、RTTIも拡張されている可能性があります。
TComponentからクラスを派生し、組み込みのストリーミングメカニズムを使用するか、RTTIを使用してINIファイルとの間でやり取りすることをお勧めします。 はるかに簡単です!
--jeroen
編集:例
まずコンポーネント:
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.
次いで、得られたDFMファイル:
object TIntegerValueComponent
IntegerValue = 33
end
DFMファイルを編集することが合理的に容易であることiniファイルと同様に、エラーが発生する可能性があるため、一般ユーザーが編集することはお勧めしません。
ストリームへの/からの基本ストリーミングと、バイナリフォーマットからテキストフォーマットへの変換が必要です(メモリが私に正しければ、テキストフォーマットはDelphi 5以降のデフォルトです)読むのがはるかに簡単です)。
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.
し、この例では、(最初の形式コードは、フォームのDFM)を動作するはず: 最も重要な線はRegisterClass(TIntegerValueComponent)です。、それは忘れやすいので。コードの残りはかなり簡単です。
また、コンポーネントをクリップボードにコピーして貼り付けることもできます。 バイナリ形式を使用してクリップボードとの間でストリーミングされます。
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;
最後に、フォームの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
は、DFMファイルを取得するための例を掲載しました。まもなく私のブログに掲載します。 –
また、この質問の受け入れられたコメントを見ることもできます:http://stackoverflow.com/questions/1293504/what-is-the-best-way-to-serialize-delphi-application-configuration RTTIを自分でやること。 –