如果您是 Delphi 2010(及更高版本)用户,则有一个新的 RTTI 单元 (rtti.pas)。您可以使用它来获取有关您的类及其属性的运行时信息(默认情况下为公共属性,但您可以使用{$RTTI} 编译器指令来包含受保护和私有字段信息)。
例如,我们有下一个包含 3 个公共字段(1 个布尔字段和 2 个字符串字段(其中一个是只读字段))的测试类。
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 和其他(看看typinfo.pas 中的TTypeKind)
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
也看看属性,我认为用一些属性标记属性(你需要重置)是个好主意,并且可能使用默认值,例如:
[ResetTo('my initial value')]
property MyValue : string read FValue write FValue;
那么您可以只过滤带有ResetToAttribute 标记的属性