我的Delphi应用程序中有一个类,我想要一种简单而动态的方法将所有字符串属性重置为'',并将所有布尔属性重置为False 据我所知,在网上应该可以制作某种循环,但是我怎么做并不清楚。
答案 0 :(得分:15)
如果您是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;
枚举对象的所有属性并将其值设置为 default ,您可以使用下面的代码。
首先,你必须初始化TRttiContext
结构(它不是必需的,因为它是一个记录)。然后你应该得到关于你的obejct的rtti信息,然后你可以循环你的属性并过滤它(跳过readonly属性,而不是boolean和stirng)。考虑到几种字符串: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
还要看一下属性,最好用一些属性标记属性(需要重置),并且可以使用默认值,如:
[ResetTo('my initial value')]
property MyValue : string read FValue write FValue;
然后您只能过滤标有ResetToAttribute
答案 1 :(得分:10)
请注意,以下代码仅适用于类的已发布属性!此外,传递给下面函数的类的实例必须至少已定义已发布的部分!
以下是如何使用旧样式RTTI将已发布的字符串属性值设置为空字符串,将布尔值设置为False。
如果你的Delphi比Delphi 2009旧,你可能会错过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;