Delphiアプリにクラスがあり、すべての文字列プロパティを''にリセットし、すべてのブールプロパティをFalseにリセットする簡単で動的な方法が必要です。Webで確認できる限り、ループを作成できるはずです。ある種のことですが、それをどのように行うかは私にはわかりません。
2 に答える
Delphi 2010(およびそれ以降)のユーザーの場合は、新しいRTTIユニット(rtti.pas)があります。これを使用して、クラスとそのプロパティに関する実行時情報を取得できます(デフォルトではパブリックプロパティですが、{$RTTI}
コンパイラ指令を使用して保護フィールドとプライベートフィールドの情報を含めることができます)。たとえば、3つのパブリックフィールド(1つのブールフィールドと2つの文字列フィールド(そのうちの1つは読み取り専用))を持つ次のテストクラスがあります。
TTest = class(TObject)
strict private
FString1 : string;
FString2 : string;
FBool : boolean;
public
constructor Create();
procedure PrintValues();
property String1 : string read FString1 write FString1;
property String2 : string read FString2;
property BoolProp : boolean read FBool write FBool;
end;
constructor TTest.Create();
begin
FBool := true;
FString1 := 'test1';
FString2 := 'test2';
end;
procedure TTest.PrintValues();
begin
writeln('string1 : ', FString1);
writeln('string2 : ', FString2);
writeln('bool: ', BoolToStr(FBool, true));
end;
オブジェクトのすべてのプロパティを列挙し、その値をデフォルトに設定するには、以下のコードのようなものを使用できます。まず、TRttiContext
構造を初期化する必要があります(レコードであるため、必須ではありません)。次に、オブジェクトに関するrtti情報を取得する必要があります。その後、プロパティをループしてフィルタリングできます(読み取り専用プロパティをスキップし、ブール値と攪拌以外)。文字列の種類が少ないことを考慮に入れてください:tkUString、tkStringなど(で見てTTypeKind
くださいtypinfo.pas
)
TObjectReset = record
strict private
public
class procedure ResetObject(obj : TObject); static;
end;
{ TObjectReset }
class procedure TObjectReset.ResetObject(obj: TObject);
var ctx : TRttiContext;
rt : TRttiType;
prop : TRttiProperty;
value : TValue;
begin
ctx := TRttiContext.Create();
try
rt := ctx.GetType(obj.ClassType);
for prop in rt.GetProperties() do begin
if not prop.IsWritable then continue;
case prop.PropertyType.TypeKind of
tkEnumeration : value := false;
tkUString : value := '';
else continue;
end;
prop.SetValue(obj, value);
end;
finally
ctx.Free();
end;
end;
テストする簡単なコード:
var t : TTest;
begin
t := TTest.Create();
try
t.PrintValues();
writeln('reset values'#13#10);
TObjectReset.ResetObject(t);
t.PrintValues();
finally
readln;
t.Free();
end;
end.
結果は
string1 : test1
string2 : test2
bool: True
reset values
string1 :
string2 : test2
bool: False
また、属性を見てください。imoプロパティ(リセットする必要がある)に何らかの属性をマークすることをお勧めします。デフォルト値は次のようになります。
[ResetTo('my initial value')]
property MyValue : string read FValue write FValue;
次に、でマークされているプロパティのみをフィルタリングできますResetToAttribute
次のコードは、クラスの公開されたプロパティに対してのみ機能することに注意してください。また、以下の関数に渡されるクラスのインスタンスには、少なくとも公開されたセクションが定義されている必要があります。
古いスタイルのRTTIを使用して、公開された文字列プロパティ値を空の文字列に設定し、ブール値をFalseに設定する方法を次に示します。
Delphi 2009より古いDelphiを使用している場合は、tkUStringタイプが欠落している可能性があります。
その場合は、次のコードから削除してください。
uses
TypInfo;
procedure ResetPropertyValues(const AObject: TObject);
var
PropIndex: Integer;
PropCount: Integer;
PropList: PPropList;
PropInfo: PPropInfo;
const
TypeKinds: TTypeKinds = [tkEnumeration, tkString, tkLString, tkWString,
tkUString];
begin
PropCount := GetPropList(AObject.ClassInfo, TypeKinds, nil);
GetMem(PropList, PropCount * SizeOf(PPropInfo));
try
GetPropList(AObject.ClassInfo, TypeKinds, PropList);
for PropIndex := 0 to PropCount - 1 do
begin
PropInfo := PropList^[PropIndex];
if Assigned(PropInfo^.SetProc) then
case PropInfo^.PropType^.Kind of
tkString, tkLString, tkUString, tkWString:
SetStrProp(AObject, PropInfo, '');
tkEnumeration:
if GetTypeData(PropInfo^.PropType^)^.BaseType^ = TypeInfo(Boolean) then
SetOrdProp(AObject, PropInfo, 0);
end;
end;
finally
FreeMem(PropList);
end;
end;
簡単なテストコードを次に示します(プロパティを公開する必要があります。クラスに公開されたプロパティがない場合は、少なくとも空の公開セクションが存在する必要があります)。
type
TSampleClass = class(TObject)
private
FStringProp: string;
FBooleanProp: Boolean;
published
property StringProp: string read FStringProp write FStringProp;
property BooleanProp: Boolean read FBooleanProp write FBooleanProp;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
SampleClass: TSampleClass;
begin
SampleClass := TSampleClass.Create;
try
SampleClass.StringProp := 'This must be cleared';
SampleClass.BooleanProp := True;
ResetPropertyValues(SampleClass);
ShowMessage('StringProp = ' + SampleClass.StringProp + sLineBreak +
'BooleanProp = ' + BoolToStr(SampleClass.BooleanProp));
finally
SampleClass.Free;
end;
end;