* Patch from Henrique Werlang to rework GetProperties so it is faster (bug ID 37850).

This commit is contained in:
michael 2020-10-06 11:24:53 +00:00
parent 69c9c7ce6d
commit 557a61a21a

View File

@ -25,7 +25,6 @@ resourcestring
SErrTypeIsNotEnumerated = 'Type %s is not an enumerated type'; SErrTypeIsNotEnumerated = 'Type %s is not an enumerated type';
type type
{ TValue } { TValue }
TValue = record TValue = record
@ -162,7 +161,8 @@ type
property IsVarArgs: boolean read GetIsVarArgs; property IsVarArgs: boolean read GetIsVarArgs;
//function GetParameters: //function GetParameters:
end; end;
TRttiMethodArray = array of TRttiMethod;
TRttiMethodArray = specialize TArray<TRttiMethod>;
{ TRttiProperty } { TRttiProperty }
@ -188,7 +188,8 @@ type
property IsWritable: boolean read GetIsWritable; property IsWritable: boolean read GetIsWritable;
property Visibility: TMemberVisibility read GetVisibility; property Visibility: TMemberVisibility read GetVisibility;
end; end;
TRttiPropertyArray = array of TRttiProperty;
TRttiPropertyArray = specialize TArray<TRttiProperty>;
{ TRttiType } { TRttiType }
@ -242,16 +243,24 @@ type
{ TRttiStructuredType } { TRttiStructuredType }
TRttiStructuredType = class abstract(TRttiType) TRttiStructuredType = class abstract(TRttiType)
private
FMethods: TRttiMethodArray;
FProperties: TRttiPropertyArray;
protected protected
function GetAncestor: TRttiStructuredType; virtual; abstract; function GetAncestor: TRttiStructuredType; virtual; abstract;
function GetStructTypeInfo: TTypeInfoStruct;
public
constructor Create(ATypeInfo: PTypeInfo);
destructor Destroy; override;
function GetDeclaredMethods: TRttiMethodArray;
function GetDeclaredProperties: TRttiPropertyArray; override; function GetDeclaredProperties: TRttiPropertyArray; override;
function GetMethod(const aName: String): TRttiMethod; override; function GetMethod(const aName: String): TRttiMethod; override;
function GetMethods: TRttiMethodArray; override; function GetMethods: TRttiMethodArray; override;
function GetMethods(const aName: String): TRttiMethodArray; override; function GetMethods(const aName: String): TRttiMethodArray; override;
function GetProperties: TRttiPropertyArray;
function GetProperty(const AName: string): TRttiProperty; override; function GetProperty(const AName: string): TRttiProperty; override;
function GetStructTypeInfo: TTypeInfoStruct;
public
constructor Create(ATypeInfo: PTypeInfo);
property StructTypeInfo: TTypeInfoStruct read GetStructTypeInfo; property StructTypeInfo: TTypeInfoStruct read GetStructTypeInfo;
end; end;
@ -720,27 +729,22 @@ end;
function TRttiStructuredType.GetMethods: TRttiMethodArray; function TRttiStructuredType.GetMethods: TRttiMethodArray;
var var
A, MethodCount: Integer; A, Start: Integer;
BaseClass: TRttiStructuredType; BaseClass: TRttiStructuredType;
Declared: TRttiMethodArray;
begin begin
BaseClass := Self; BaseClass := Self;
MethodCount := 0; Result := nil;
while Assigned(BaseClass) do while Assigned(BaseClass) do
begin begin
Inc(MethodCount, BaseClass.StructTypeInfo.MethodCount); Declared := BaseClass.GetDeclaredMethods;
BaseClass := BaseClass.GetAncestor; Start := Length(Result);
end; SetLength(Result, Start + Length(Declared));
SetLength(Result, MethodCount); for A := Low(Declared) to High(Declared) do
BaseClass := Self; Result[Start + A] := Declared[A];
MethodCount:=0;
while Assigned(BaseClass) do
begin
for A := 0 to Pred(BaseClass.StructTypeInfo.MethodCount) do
begin
Result[MethodCount] := TRttiMethod.Create(BaseClass, BaseClass.StructTypeInfo.GetMethod(A));
Inc(MethodCount);
end;
BaseClass := BaseClass.GetAncestor; BaseClass := BaseClass.GetAncestor;
end; end;
end; end;
@ -764,6 +768,32 @@ begin
end; end;
end; end;
function TRttiStructuredType.GetProperties: TRttiPropertyArray;
var
A, Start: Integer;
BaseClass: TRttiStructuredType;
Declared: TRttiPropertyArray;
begin
BaseClass := Self;
Result := nil;
while Assigned(BaseClass) do
begin
Declared := BaseClass.GetDeclaredProperties;
Start := Length(Result);
SetLength(Result, Start + Length(Declared));
for A := Low(Declared) to High(Declared) do
Result[Start + A] := Declared[A];
BaseClass := BaseClass.GetAncestor;
end;
end;
function TRttiStructuredType.GetMethod(const aName: String): TRttiMethod; function TRttiStructuredType.GetMethod(const aName: String): TRttiMethod;
var var
Method: TRttiMethod; Method: TRttiMethod;
@ -776,53 +806,30 @@ end;
function TRttiStructuredType.GetProperty(const AName: string): TRttiProperty; function TRttiStructuredType.GetProperty(const AName: string): TRttiProperty;
var var
A : Integer; Prop: TRttiProperty;
BaseClass : TRttiStructuredType;
begin begin
BaseClass := Self; for Prop in GetProperties do
while Assigned(BaseClass) do if Prop.Name = AName then
begin Exit(Prop);
for A := 0 to Pred(BaseClass.StructTypeInfo.PropCount) do
if StructTypeInfo.GetProp(A).Name = AName then
Exit(TRttiProperty.Create(BaseClass, BaseClass.StructTypeInfo.GetProp(A)));
BaseClass:=BaseClass.GetAncestor;
end;
end; end;
function TRttiStructuredType.GetDeclaredProperties: TRttiPropertyArray; function TRttiStructuredType.GetDeclaredProperties: TRttiPropertyArray;
var var
A, PropertyCount: Integer; A, PropCount: Integer;
BaseClass: TRttiStructuredType;
begin begin
BaseClass := Self; if not Assigned(FProperties) then
PropertyCount := 0;
while Assigned(BaseClass) do
begin begin
Inc(PropertyCount, BaseClass.StructTypeInfo.PropCount); PropCount := StructTypeInfo.PropCount;
BaseClass := BaseClass.GetAncestor; SetLength(FProperties, PropCount);
for A := 0 to Pred(PropCount) do
FProperties[A] := TRttiProperty.Create(Self, StructTypeInfo.GetProp(A));
end; end;
SetLength(Result, PropertyCount); Result := FProperties;
BaseClass := Self;
PropertyCount := 0;
while Assigned(BaseClass) do
begin
for A := 0 to Pred(BaseClass.StructTypeInfo.PropCount) do
begin
Result[PropertyCount] := TRttiProperty.Create(BaseClass, BaseClass.StructTypeInfo.GetProp(A));
Inc(PropertyCount);
end;
BaseClass := BaseClass.GetAncestor;
end;
end; end;
function TRttiStructuredType.GetStructTypeInfo: TTypeInfoStruct; function TRttiStructuredType.GetStructTypeInfo: TTypeInfoStruct;
@ -838,6 +845,41 @@ begin
inherited Create(ATypeInfo); inherited Create(ATypeInfo);
end; end;
destructor TRttiStructuredType.Destroy;
var
Method: TRttiMethod;
Prop: TRttiProperty;
begin
for Method in FMethods do
Method.Free;
for Prop in FProperties do
Prop.Free;
inherited Destroy;
end;
function TRttiStructuredType.GetDeclaredMethods: TRttiMethodArray;
var
A, MethodCount: Integer;
BaseClass: TRttiStructuredType;
begin
if not Assigned(FMethods) then
begin
MethodCount := StructTypeInfo.MethodCount;
SetLength(FMethods, MethodCount);
for A := 0 to Pred(MethodCount) do
FMethods[A] := TRttiMethod.Create(Self, StructTypeInfo.GetMethod(A));
end;
Result := FMethods;
end;
{ TRttiInstanceType } { TRttiInstanceType }
function TRttiInstanceType.GetClassTypeInfo: TTypeInfoClass; function TRttiInstanceType.GetClassTypeInfo: TTypeInfoClass;