2017-03-16 74 views
2

我需要遍歷一個使用RTTI具有複雜結構的類。該類有幾個記錄成員,我也想迭代。Delphi - 將TValue傳遞到泛型方法

TRTTIHelpers<T> = class 
    public 
    class function DoGetValuesForClass(aClassInst: T): TStringList; 
    class function DoGetValuesForRecord(aRec: T): TStringList; 
    end; 

我知道當我在這是一個創紀錄的類成員:

for prop in rt.GetProperties() do 
    begin 
     if prop.PropertyType is TRttiRecordType then 
     begin 
     lValue := prop.GetValue(aInst); 
     Result.AddStrings(TRTTIHelpers<T>.DoGetValuesForRecord(TValue)); <-- 
     end 

我怎樣才能通過TValue作爲參數傳遞給DoGetValuesForRecord,所以我也可以通過記錄重複?

回答

7

使用的TValueAsType<T>方法將值轉換爲T

lValue := prop.GetValue(aInst); 
Result.AddStrings(TRTTIHelpers<T>.DoGetValuesForRecord(lValue.AsType<T>)); 

這個簡單的程序說明了這一點:

{$APPTYPE CONSOLE} 

uses 
    System.RTTI; 

type 
    TMyRecord = record 
    foo: Integer; 
    end; 

    TMyClass = class 
    function GetRec: TMyRecord; 
    property Rec: TMyRecord read GetRec; 
    function GetInt: Integer; 
    property Int: Integer read GetInt; 
    end; 

function TMyClass.GetRec: TMyRecord; 
begin 
    Result.foo := 42; 
end; 

function TMyClass.GetInt: Integer; 
begin 
    Result := 666; 
end; 

procedure Main; 
var 
    inst: TMyClass; 
    ctx: TRttiContext; 
    typ: TRttiType; 
    prop: TRttiProperty; 
    value: TValue; 
    rec: TMyRecord; 
begin 
    inst := TMyClass.Create; 
    typ := ctx.GetType(TypeInfo(TMyClass)); 
    for prop in typ.GetProperties do begin 
    if prop.Name='Rec' then begin 
     value := prop.GetValue(inst); 
     rec := value.AsType<TMyRecord>; 
     Writeln(rec.foo); 
    end; 
    end; 
end; 

begin 
    try 
    Main; 
    except 
    on E: Exception do 
     Writeln(E.ClassName, ': ', E.Message); 
    end; 
    Readln; 
end. 

當然,這並不需要的財產prop是的正確的類型。如果沒有,那麼你會遇到運行時錯誤。在我上面的示例中,我確保通過測試屬性的名稱來確保獲得所需的屬性。如果刪除該測試,則程序將失敗,並顯示運行時間爲EInvalidCast的錯誤。

看着你的代碼我懷疑你很可能會遇到這樣的錯誤。如果rt的每一個財產屬於同一類型,那將是令人驚訝的。

看着TRTTIHelpers<T>我認爲這對你目前的形式不會很有用。至少,你將無法與基於RTTI的代碼良好地交互。原因是調用TRTTIHelpers<T>需要您在編譯時提供類型參數。但是對於RTTI代碼,在編譯時你不知道這種類型。我懷疑TRTTIHelpers<T>應該不是泛型類,而是使用RTTI類型爲您提供功能,這對於運行時確定的鍵入來說是靈活的。這個建議當然可能是錯誤的,但是我只有這個問題中的一小段代碼來指導我。

+0

嗯,這是你問的問題的答案。運行時錯誤告訴你,無論'lValue'是什麼,都不是'T'類型。 –

+0

lValue中的內容是TRTTIRecordType類型 - 如果prop.PropertyType是TRttiRecordType,那麼 - 並且我在我的類中有記錄類型 – RBA

+0

是,記錄類型。但不一定與通用'T'類型相同,因爲運行時錯誤會通知您。 –

相關問題