레코드는 RTTI를 가질 수 있지만 참조 카운트 필드 (문자열 또는 인터페이스 등)가 하나 이상인 경우에만 가능합니다. 그리고 그 기록 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 파일 : DFM 파일을 편집 할 합리적으로 쉽다는 것을
object TIntegerValueComponent
IntegerValue = 33
end
, 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.
그리고,이 예 (제 1 형태의 코드, 그 형태 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 파일을 가져 오는 예를 게시; 곧 나의 blog에 그것을 게시 할 것이다. –
이 질문에 대한 받아 들인 코멘트를보고 싶을 수도 있습니다. http://stackoverflow.com/questions/1293504/what-is-the-best-way-to-serialize-delphi-application-configuration RTTI에 직접 참여하십시오. –