2010-10-09 71 views
5

我目前使用這段代碼,但沒有列出任何東西。我錯過了什麼?如何使用rtti列出屬性的屬性?

program ListAttrs; 

{$APPTYPE CONSOLE} 

uses 
    Rtti, 
    SysUtils; 

type 
    TPerson = class 
    private 
    FName: String; 
    FAge: Integer; 
    public 
    [NonEmptyString('Must provide a Name')] 
    property Name : String read FName write FName; 
    [MinimumInteger(18, 'Must be at least 18 years old')] 
    [MaximumInteger(65, 'Must be no older than 65 years')] 
    property Age : Integer read FAge write FAge; 
    end; 


procedure test; 
var 
    ctx  : TRttiContext; 
    lType  : TRttiType; 
    lAttribute: TCustomAttribute; 
    lProperty : TRttiProperty; 
begin 
    ctx  := TRttiContext.Create; 
    lType  := ctx.GetType(TPerson); 
    for lProperty in lType.GetProperties do 
    for lAttribute in lProperty.GetAttributes do 
    Writeln(lAttribute.ToString); 
end; 

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

回答

5

看看你的編譯器警告。當我建立這個,我看到:

[DCC Warning] ListAttrs.dpr(15): W1025 Unsupported language feature: 'custom attribute' 
[DCC Warning] ListAttrs.dpr(17): W1025 Unsupported language feature: 'custom attribute' 
[DCC Warning] ListAttrs.dpr(18): W1025 Unsupported language feature: 'custom attribute' 

這是由於歷史的怪癖。 Delphi for .NET編譯器支持屬性,它們在VCL中廣泛用於各種.NET事物。 Delphi for Win32編譯器必須能夠讀取它們並忽略它們。

然後Delphi 2010出來了,Delphi Win32突然支持屬性。但是Delphi中並不存在所有這些.NET屬性。他們並沒有將它們全部搞定,而是讓編譯器給出警告,然後忽略它們。 (另外,我相信我聽說Emb的一個人說Delphi for .NET仍然在內部使用,無論什麼原因。)

作爲一個副作用,放置一個實際上並不存在的屬性是完全有效的你的課程。它只會被編譯器忽略,並且不會生成RTTI。

+0

非常感謝梅森。 – Salvador 2010-10-10 04:45:00

+2

爲了補充說明,如果您想在代碼中使用自定義屬性,並讓它們可以被RTTI訪問,那麼您需要在代碼中明確定義屬性類。有關此主題的2010年文檔中有一整章:ms-help://embarcadero.rs2010/rad/Attributes_Index.html – 2010-10-11 20:37:56