2015-12-21 69 views
2

擴展的RTTI具有GetDeclaredProperties函數,這正是我所需要的,但是如果我在多線程中使用擴展RTTI時遇到問題。可能只循環一個類的​​聲明屬性?

因此,我使用GetPropList,但這給了我所有屬性的列表 - 不僅發佈在當前類(或明確聲明)。

TBaseSettings = class(TPersistent) 
published 
    property Charset: string read FCharset write FCharset; 
end; 

TBasicSettings = class(TBaseSettings) 
published 
    property forums: Variant read fforums write fforums; 
end; 

TConcreteSettings = class(TBasicSettings) 
published 
    property forums; // <-- make it explicit visible: OK 
    property prefix: Variant read fprefix write fprefix; // <-- OK 
end; 

我不想讀字符集財產。

我的第一個猜測是使用的https://stackoverflow.com/a/1565686修改後的版本來檢查繼承,但實際上論壇屬性也繼承。

也許這對傳統的RTTI來說是不可能的?我使用的是德爾福2010.

+0

使用GetDeclaredPropeties –

+0

我最終更改了基類中的屬性代碼,我不希望稍後在GetPropList循環中將其標記爲* public *並且未發佈。這不是我想要存檔的東西,但是現在對我來說可行了:)感謝你*豎起大拇指* – geskill

回答

2

如果您的代碼以調用GetPropList類似的方式調用GetDeclaredPropList很方便,請參閱下文。我已經重寫了Delphi 7中的代碼,我相信它也可以在Delphi 2010中工作(我沒有這個功能)。

type 
    PPropData = ^TPropData; 

function AfterString(P: Pointer): Pointer; 
begin 
    Result := Pointer(NativeUInt(P) + (PByte(P)^ + 1)); 
end; 

function GetPropData(TypeData: PTypeData): PPropData; 
begin 
    Result := AfterString(@TypeData^.UnitName); 
end; 

function NextPropInfo(PropInfo: PPropInfo): PPropInfo; 
begin 
    Result := AfterString(@PropInfo^.Name); 
end; 

procedure GetDeclaredPropInfos(TypeInfo: PTypeInfo; PropList: PPropList); 
var 
    TypeData: PTypeData; 
    PropData: PPropData; 
    PropInfo: PPropInfo; 
    I: Integer; 
begin 
    TypeData := GetTypeData(TypeInfo); 
    PropData := GetPropData(TypeData); 
    FillChar(PropList^, Sizeof(PPropInfo) * PropData^.PropCount, 0); 
    PropInfo := PPropInfo(@PropData^.PropList); 
    for I := 0 to PropData^.PropCount - 1 do 
    begin 
    PropList^[I] := PropInfo; 
    PropInfo := NextPropInfo(PropInfo); 
    end; 
end; 

function GetDeclaredPropList(TypeInfo: PTypeInfo; out PropList: PPropList): Integer; overload; 
begin 
    Result := GetPropData(GetTypeData(TypeInfo))^.PropCount; 
    if Result > 0 then 
    begin 
    GetMem(PropList, Result * SizeOf(Pointer)); 
    GetDeclaredPropInfos(TypeInfo, PropList); 
    end; 
end; 

function GetDeclaredPropList(AObject: TObject; out PropList: PPropList): Integer; overload; 
begin 
    Result := GetDeclaredPropList(PTypeInfo(AObject.ClassInfo), PropList); 
end; 

// example usage: 
var 
    I, Count: Integer; 
    PropList: PPropList; 
    PropInfo: PPropInfo; 
begin 
    Count := GetDeclaredPropList(TypeInfo(TConcreteSettings), PropList); 
    try 
    for I := 0 to Count - 1 do 
    begin 
     PropInfo := PropList^[I]; 
     Writeln(PropInfo^.Name); 
    end; 
    finally 
    FreeMem(PropList); 
    end; 
end. 
+0

事實上,這將與Delphi XE +一起使用,但是在Delphi 2010中沒有'TTypeData.PropData'和'TPropInfo .Tail'功能:/ PropData屬性僅在註釋中存在。 – geskill

+0

@geskill我已經重寫了Delphi 7中的代碼,參見上文。 –

+0

這個工作,在D2010中已經定義了'PPropData',太好了!這也允許定義已發佈屬性的自定義排序=) – geskill

0
var 
    TypeData: PTypeData; 
    PropData: PPropData; 
    PropInfo: PPropInfo; 
    I: Integer; 
begin 
    TypeData := GetTypeData(TypeInfo(TConcreteSettings)); 
    PropData := GetPropData(TypeData); 
    if Assigned(PropData) then 
    begin 
    PropInfo := @PropData^.PropList; 
    for I := 0 to PropData^.PropCount - 1 do 
    begin 
     Writeln(PropInfo^.Name); 
     PropInfo := NextPropInfo(PropInfo); 
    end; 
    end; 
end; 

對於實施GetPropDataNextPropInfo看我上面的其他answer