2017-02-21 65 views
1

我們需要使用具有預設值的rtti創建一個類。這些值取自屬性。當你需要在現場增加價值的時候,所有的東西看起來都很好。找到正確的屬性並獲取該屬性的值爲true。但該記錄沒有運行。告訴我哪裏錯了?通過RTTI記錄該字段中的值

program DemoGenerator; 
{$APPTYPE CONSOLE} 
{$R *.res} 

uses 
    System.SysUtils, 
    System.Rtti; 

Type 
    // My attribute 
    DemoDataAttribute = class(TCustomAttribute) 
    private 
    FGenerator: String; 
    public 
    constructor Create(Generator: String); 
    published 
    property Generator: string read FGenerator write FGenerator; 
    end; 

    // 
    TSomeType = Class 
    private 
    fPhone: string; 
    published 
    [DemoData('+1800764328')] 
    property Phone: string read fPhone write fPhone; 
    End; 

    // 
    TMegaSuperClass = Class 
    Function Go<T: Class, constructor>: T; 
    End; 

Procedure Test; 
var 
    LMsc: TMegaSuperClass; 
    New: TSomeType; 
Begin 
    LMsc := TMegaSuperClass.Create; 
    try 
    New := LMsc.Go<TSomeType>; 
    Writeln('New.Phone: ' + New.Phone); 
    finally 
    LMsc.Free; 
    // New.Free; 
    end; 
End; 

{ DemoDataAttribute } 

constructor DemoDataAttribute.Create(Generator: String); 
begin 
    FGenerator := Generator; 
end; 

{ TMegaSuperClass } 

function TMegaSuperClass.Go<T>: T; 
var 
    LContext: TRttiContext; 
    LClass: TRttiInstanceType; 
    LProp: TRttiProperty; 
    LAttr: TCustomAttribute; 
    LField: TRttiField; 
begin 
    // Init Rtti 
    LContext := TRttiContext.Create; 
    LClass := LContext.GetType(T) as TRttiInstanceType; 
    Writeln('LClass: ' + LClass.ToString); 
    // Result 
    Result := T.Create; 
    for LProp in LClass.GetProperties do 
    begin 
    Writeln('LProp: ' + LProp.ToString); 
    for LAttr in LProp.GetAttributes do 
    begin 
     Writeln('LAttr: ' + LAttr.ToString); 
     if LAttr is DemoDataAttribute then 
     Begin 
     Writeln('Attr value: ' + DemoDataAttribute(LAttr).Generator); 
     // How write value? 
     LProp.SetValue(@Result, DemoDataAttribute(LAttr).Generator); 
     End; 
    end; 
    end; 
end; 

begin 
    try 
    { TODO -oUser -cConsole Main : Insert code here } 
    Test; 
    Readln; 
    except 
    on E: Exception do 
     Writeln(E.ClassName, ': ', E.Message); 
    end; 

end. 

控制檯輸出:

TSomeType
財產電話:字符串
DemoDataAttribute
值:1800764328
電話:

回答

3

像這樣:

LProp.SetValue(Pointer(Result), DemoDataAttribute(LAttr).Generator); 

SetValue的第一個參數被聲明爲Instance: Pointer。類引用只是指向實例的指針,這就是你想要的。

+1

我認爲對'指針'的轉換是必要的,但現在不能檢查。 –

+0

演員需要(否則不會編譯)。你也可以像這樣轉換:'TObject(Result)',它也可以。事情是我真的不明白爲什麼需要這樣的轉換,因爲編譯器可以通過泛型的當前約束找出它(不應該使用類和構造函數約束意味着TObject後代?) –

相關問題