链接到原始问题是否有可能获得类属性的索引?并由Remy Lebeau和RRUZ回答
program Demo;
{$APPTYPE CONSOLE}
uses
System.SysUtils, Winapi.Windows,
System.Rtti, System.TypInfo;
type
TMyClass = class
private
function GetInteger(const Index: Integer): Integer;
procedure SetInteger(const Index, Value: Integer);
public
property P1: Integer Index 1 read GetInteger write SetInteger;
property P2: Integer Index 2 read GetInteger write SetInteger;
property P3: Integer Index 3 read GetInteger write SetInteger;
end;
{ TMyClass }
function TMyClass.GetInteger(const Index: Integer): Integer;
begin
Result := Index;
end;
procedure TMyClass.SetInteger(const Index, Value: Integer);
begin
//
end;
{------------------------------------------------------------------------------}
function GetPropertyIndex(const AClass: TClass; APropertyName: string): Integer;
var
Ctx: TRttiContext;
begin
Ctx := TRttiContext.Create;
Result := (Ctx.GetType(AClass).GetProperty(APropertyName) as TRttiInstanceProperty).Index;
end;
{------------------------------------------------------------------------------}
var
C: Cardinal;
I: Integer;
N: Integer;
begin
try
C := GetTickCount;
for N := 1 to 1000000 do
I := GetPropertyIndex(TMyClass, 'P2');
WriteLn(GetTickCount - C, ' ms - The index of the property P2 is ', I);
ReadLn;
except
on E: Exception do Writeln(E.ClassName, ': ', E.Message);
end;
end.
Run Code Online (Sandbox Code Playgroud)
在我的电脑上,这个测试大约需要5秒.但是当我TRttiContext在打电话之前使用时GetPropertyIndex()- 例如
...
begin
try
TRttiContext.Create.Free;
C := GetTickCount;
for N := 1 to 1000000 do
I := GetPropertyIndex(TMyClass, 'P2');
...
Run Code Online (Sandbox Code Playgroud)
同样的测试只需要约1秒.为什么?
编辑我在测试secon示例时发现的问题
...
var
Ctx: TRttiContext;
C: Cardinal;
I: Integer;
N: Integer;
begin
try
C := GetTickCount;
for N := 1 to 1000000 do
begin
Ctx := TRttiContext.Create;
I := (Ctx.GetType(TMyClass).GetProperty('P2') as TRttiInstanceProperty).Index;
end;
WriteLn(GetTickCount - C, ' ms - The index of the property P2 is ', I);
ReadLn;
except
on E: Exception do Writeln(E.ClassName, ': ', E.Message);
end;
end.
Run Code Online (Sandbox Code Playgroud)
但问题的原因在第二次测试中更为明显.
Rem*_*eau 10
使用引用计数池缓存RTTI数据.您的代码加速如此之快的原因是因为该TRttiContext.Create.Free语句创建的temp TRttiContext在应用程序的生命周期内保持在范围内,并维护对该池的活动引用.TRttiContext在其中创建的后续实例GetPropertyIndex()正在重新使用现有池,而不是每次都浪费时间重新创建新池.当DPR代码到达end.语句时,temp TRttiContext超出范围并释放其对池的引用.
当您删除的TRttiContext.Create.Free说法,临时TRttiContext消失,并创建和销毁每个新池TRttiContext是GetPropertyIndex()用,浪费时间遍地重新创建相同的缓存.
通过在项目选项中启用调试DCU然后单步TRttiContext调试调试器中的代码,您可以轻松地看到这一点.